Skip to content

🧬 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 Memberpublic inheritanceprotected inheritanceprivate inheritance
publicpublicprotectedprivate
protectedprotectedprotectedprivate
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 inheritance

Constructor 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

  1. Base class constructor chạy trước
  2. Derived class constructor chạy sau
  3. 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 destroyed

protected 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

ConceptKey Takeaway
InheritanceClass mới dựa trên class cũ
public inheritanceis-a relationship (phổ biến nhất)
protected membersDerived classes có thể access
Constructor orderBase → Derived
Destructor orderDerived → Base
Method hidingOverride không có virtual

➡️ Tiếp theo

Tiếp theo: Virtual Functions — True polymorphism với virtual và override.