Giao diện
🧬 Inheritance — Kế thừa
Inheritance cho phép tạo class mới dựa trên class đã có, tái sử dụng code và thiết lập quan hệ "is-a" giữa các đối tượng.
Tại sao cần Inheritance?
Vấn đề: Code Duplication
cpp
class Dog {
std::string name_;
int age_;
public:
void eat() { std::cout << name_ << " is eating\n"; }
void sleep() { std::cout << name_ << " is sleeping\n"; }
void bark() { std::cout << "Woof!\n"; }
};
class Cat {
std::string name_;
int age_; // Duplicate!
public:
void eat() { /* Same code! */ }
void sleep() { /* Same code! */ }
void meow() { std::cout << "Meow!\n"; }
};Giải pháp: Inheritance
cpp
// Base class (Parent)
class Animal {
protected:
std::string name_;
int age_;
public:
Animal(const std::string& name, int age)
: name_(name), age_(age) {}
void eat() { std::cout << name_ << " is eating\n"; }
void sleep() { std::cout << name_ << " is sleeping\n"; }
};
// Derived class (Child)
class Dog : public Animal {
public:
Dog(const std::string& name, int age)
: Animal(name, age) {} // Call base constructor
void bark() { std::cout << name_ << " says: Woof!\n"; }
};
class Cat : public Animal {
public:
Cat(const std::string& name, int age)
: Animal(name, age) {}
void meow() { std::cout << name_ << " says: Meow!\n"; }
};Cú pháp Inheritance
cpp
class Derived : access_specifier Base {
// Derived class members
};Access Specifiers cho Inheritance
| Base Member | public inheritance | protected inheritance | private inheritance |
|---|---|---|---|
public | public | protected | private |
protected | protected | protected | private |
private | ❌ không access | ❌ không access | ❌ không access |
Phổ biến nhất: public inheritance (is-a relationship)
cpp
class Dog : public Animal { }; // ✅ Phổ biến nhất
class Cat : protected Animal { }; // 🔸 Hiếm dùng
class Bird : private Animal { }; // 🔸 Implementation inheritanceConstructor trong Inheritance
Gọi Base Constructor
cpp
#include <iostream>
#include <string>
class Vehicle {
protected:
std::string brand_;
int year_;
public:
Vehicle(const std::string& brand, int year)
: brand_(brand), year_(year) {
std::cout << "Vehicle constructor called\n";
}
void showInfo() const {
std::cout << year_ << " " << brand_ << std::endl;
}
};
class Car : public Vehicle {
private:
int numDoors_;
public:
// Gọi base constructor trong initializer list
Car(const std::string& brand, int year, int doors)
: Vehicle(brand, year), // ✅ Base constructor FIRST
numDoors_(doors) {
std::cout << "Car constructor called\n";
}
void showDetails() const {
showInfo();
std::cout << "Doors: " << numDoors_ << std::endl;
}
};
int main() {
Car myCar("Toyota", 2024, 4);
myCar.showDetails();
return 0;
}Output:
Vehicle constructor called
Car constructor called
2024 Toyota
Doors: 4⚠️ Constructor Order
- Base class constructor chạy trước
- Derived class constructor chạy sau
- Destructor chạy ngược lại: Derived trước, Base sau
Destructor trong Inheritance
cpp
#include <iostream>
class Base {
public:
Base() { std::cout << "Base constructed\n"; }
~Base() { std::cout << "Base destroyed\n"; }
};
class Derived : public Base {
public:
Derived() { std::cout << "Derived constructed\n"; }
~Derived() { std::cout << "Derived destroyed\n"; }
};
int main() {
Derived d;
return 0;
}Output:
Base constructed
Derived constructed
Derived destroyed
Base destroyedprotected vs private Members
cpp
class Base {
private:
int privateVar_ = 1; // ❌ Derived cannot access
protected:
int protectedVar_ = 2; // ✅ Derived can access
public:
int publicVar_ = 3; // ✅ Everyone can access
};
class Derived : public Base {
public:
void showVars() {
// std::cout << privateVar_; // ❌ Error!
std::cout << protectedVar_; // ✅ OK
std::cout << publicVar_; // ✅ OK
}
};Method Overriding (Hiding)
cpp
#include <iostream>
class Animal {
public:
void speak() {
std::cout << "Some generic sound\n";
}
};
class Dog : public Animal {
public:
void speak() { // Hides base class method
std::cout << "Woof!\n";
}
};
int main() {
Dog d;
d.speak(); // "Woof!"
Animal a;
a.speak(); // "Some generic sound"
// ⚠️ Nhưng nếu dùng pointer...
Animal* ptr = &d;
ptr->speak(); // "Some generic sound" — NOT Woof!
// Cần virtual để fix!
}📌 Đây chỉ là Method Hiding
Để có true polymorphism, ta cần virtual functions → Xem bài tiếp theo!
Multiple Inheritance
cpp
class Flyable {
public:
void fly() { std::cout << "Flying...\n"; }
};
class Swimmable {
public:
void swim() { std::cout << "Swimming...\n"; }
};
// Duck kế thừa từ cả hai
class Duck : public Flyable, public Swimmable {
public:
void quack() { std::cout << "Quack!\n"; }
};
int main() {
Duck d;
d.fly(); // ✅ Từ Flyable
d.swim(); // ✅ Từ Swimmable
d.quack(); // ✅ Của Duck
}⚠️ Diamond Problem
Multiple inheritance có thể gây Diamond Problem. Giải pháp: virtual inheritance (advanced topic).
📚 Tổng kết
| Concept | Key Takeaway |
|---|---|
| Inheritance | Class mới dựa trên class cũ |
public inheritance | is-a relationship (phổ biến nhất) |
protected members | Derived classes có thể access |
| Constructor order | Base → Derived |
| Destructor order | Derived → Base |
| Method hiding | Override không có virtual |
➡️ Tiếp theo
Tiếp theo: Virtual Functions — True polymorphism với virtual và override.