继承与组合

翻译整理自 cppreference - 派生类。

1. 继承语法

class Animal {
public:
    void eat() { std::cout << "eat\n"; }
};

class Dog : public Animal {                  // 公有继承
public:
    void bark() { std::cout << "bark\n"; }
};

Dog d;
d.eat();                                     // 继承自 Animal
d.bark();

继承方式:

派生方式 基类 public 基类 protected 基类 private
public public protected 不可见
protected protected protected 不可见
private private private 不可见

默认 class 是 private 继承;struct 是 public 继承。

2. 构造顺序与初始化

基类构造在派生类之前,析构反之:

class Base {
public:
    Base(int x) { std::cout << "Base\n"; }
    virtual ~Base() { std::cout << "~Base\n"; }
};

class Derived : public Base {
public:
    Derived(int x, int y) : Base(x), y_(y) {
        std::cout << "Derived\n";
    }
    ~Derived() override { std::cout << "~Derived\n"; }
private:
    int y_;
};

Derived d{1, 2};
// 输出:Base / Derived / ~Derived / ~Base

3. 多重继承

class A { public: void fa(); };
class B { public: void fb(); };
class C : public A, public B { };

C c;
c.fa();
c.fb();

菱形继承与虚继承

class VBase { public: int data; };
class Left  : virtual public VBase {};
class Right : virtual public VBase {};
class Final : public Left, public Right {};

Final f;
f.data = 1;    // OK,无歧义(虚继承共享)

4. 派生类向基类转换

Derived d;
Base&   r = d;
Base*   p = &d;

切片(slicing):按值传递派生类给基类参数会丢失派生部分,应使用引用/指针。

5. 组合 has-a

class Engine {
public:
    void start() { ... }
};

class Car {
public:
    void start() { engine_.start(); }
private:
    Engine engine_;                          // 组合,强 ownership
};

6. 私有继承(实现继承)

class Timer : private Clock {
    // 内部使用 Clock,但对外不暴露
};

一般优先组合而非私有继承。

7. CRTP(奇异递归模板)

template <typename Derived>
class Base {
public:
    void interface() {
        static_cast<Derived*>(this)->impl();
    }
};

class Derived : public Base<Derived> {
public:
    void impl() { std::cout << "Derived\n"; }
};

编译期多态,零运行时开销。

小结

C++ 继承语义丰富,但优先组合是现代 C++ 的共识。下一章学习多态。