Class và Object (Lập trình hướng đối tượng)
Bài “Struct” đã giới thiệu rằng struct có thể chứa cả biến lẫn hàm thành viên, và khác class duy nhất ở mức truy cập mặc định. Từ bài này, chúng ta đi sâu vào class - nền tảng của lập trình hướng đối tượng (Object-Oriented Programming - OOP) trong C++.
Class và Object là gì?
Phần tiêu đề “Class và Object là gì?”- Class (lớp) là một “bản thiết kế” (blueprint) mô tả dữ liệu (thuộc tính) và hành vi (phương thức) của một loại đối tượng.
- Object (đối tượng) là một thực thể cụ thể được tạo ra từ class đó - giống như
struct Point p1;tạo ra một biến cụ thể từ kiểuPoint.
#include <iostream>#include <string>
class Dog {public: std::string name; int age;
void bark() { std::cout << name << " sua: Gau gau!" << std::endl; }};
int main() { Dog d1; // d1 là một object (thực thể) của class Dog d1.name = "Mực"; d1.age = 2; d1.bark(); // Mực sua: Gau gau!
return 0;}Access modifiers: public, private, protected
Phần tiêu đề “Access modifiers: public, private, protected”Khác với struct (mặc định public), thành viên của class mặc định là private - không thể truy cập từ bên ngoài class. C++ có 3 mức truy cập:
| Mức truy cập | Truy cập từ bên ngoài class | Truy cập từ class con (kế thừa) |
|---|---|---|
public |
Được | Được |
protected |
Không | Được |
private |
Không | Không |
#include <iostream>
class BankAccount {private: double balance; // Chỉ truy cập được từ bên trong class
public: void deposit(double amount) { if (amount > 0) { balance += amount; } }
double getBalance() { return balance; }};
int main() { BankAccount acc; // acc.balance = 1000; // LỖI! balance là private acc.deposit(1000); // OK - deposit là public std::cout << acc.getBalance() << std::endl; // 1000
return 0;}Encapsulation (đóng gói)
Phần tiêu đề “Encapsulation (đóng gói)”Encapsulation là nguyên tắc giấu dữ liệu nội bộ (private) và chỉ cho phép thay đổi/đọc dữ liệu đó thông qua các phương thức công khai (public), thường gọi là getter và setter. Điều này giúp class kiểm soát được dữ liệu của nó luôn hợp lệ.
#include <iostream>
class BankAccount {private: double balance;
public: void setBalance(double amount) { if (amount < 0) { std::cout << "So du khong the am!" << std::endl; return; } balance = amount; }
double getBalance() { return balance; }};
int main() { BankAccount acc; acc.setBalance(-500); // So du khong the am! acc.setBalance(500); std::cout << acc.getBalance() << std::endl; // 500
return 0;}Nhờ encapsulation, balance không thể bị gán một giá trị âm bất hợp lệ từ bên ngoài - mọi thay đổi đều phải đi qua setBalance(), nơi có kiểm tra hợp lệ.
Hàm thành viên định nghĩa bên ngoài class
Phần tiêu đề “Hàm thành viên định nghĩa bên ngoài class”Với class lớn, người ta thường chỉ khai báo (declare) phương thức bên trong class, rồi định nghĩa (define) chi tiết bên ngoài bằng toán tử phạm vi :: (scope resolution operator):
#include <iostream>
class Rectangle {public: double width; double height;
double area(); // Chỉ khai báo};
double Rectangle::area() { // Định nghĩa bên ngoài class return width * height;}
int main() { Rectangle r; r.width = 4; r.height = 5; std::cout << r.area() << std::endl; // 20
return 0;}struct vs class: khi nào dùng cái nào?
Phần tiêu đề “struct vs class: khi nào dùng cái nào?”- Dùng
structcho các kiểu dữ liệu đơn giản, chỉ gộp vài trường dữ liệu liên quan (ví dụPoint { int x, y; }), không cần che giấu dữ liệu. - Dùng
classkhi cần encapsulation thật sự: dữ liệu nội bộ cần được bảo vệ, kiểm soát truy cập, hoặc class có nhiều logic nghiệp vụ phức tạp.
Tổng kết
Phần tiêu đề “Tổng kết”classlà bản thiết kế,objectlà thực thể cụ thể được tạo ra từ class đó- Thành viên của
classmặc định làprivate, khác vớistruct(mặc địnhpublic) - Ba mức truy cập:
public(mọi nơi),protected(class và class con),private(chỉ trong class) - Encapsulation: giấu dữ liệu
private, chỉ cho truy cập qua getter/setterpublicđể đảm bảo dữ liệu luôn hợp lệ - Có thể khai báo phương thức trong class và định nghĩa chi tiết bên ngoài bằng
::