继承与组合
翻译整理自 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++ 的共识。下一章学习多态。