继承允许派生类在基类已有成员与行为之上扩展或特化,形成 is-a 关系(例如狗是一种动物)。C++ 支持 public、protected、private 继承;public 继承时基类 public 成员在派生类中仍为 public。本节说明派生类定义、构造与析构顺序、名字隐藏与对象切片,为多态铺垫。
基本语法
#include <iostream>
#include <string>
class Animal {
public:
std::string name;
void speak() const { std::cout << name << " makes a sound\n"; }
};
class Dog : public Animal {
public:
void speak() const { std::cout << name << " barks\n"; }
};
int main() {
Dog d;
d.name = "Rex";
d.speak();
return 0;
}典型输出:Rex barks。Dog : public Animal 表示公有继承;派生类对象包含基类子对象,可访问基类 public / protected 成员(依继承方式而定)。
继承方式与访问
| 继承方式 | 基类 public 成员在派生类中 | 常见语义 |
|---|---|---|
public | public | 接口继承,is-a |
protected | protected | 实现继承,较少对外暴露 |
private | private | 实现细节复用,非 is-a 对外表达 |
构造与析构顺序
#include <iostream>
class Base {
public:
Base() { std::cout << "Base 构造\n"; }
~Base() { std::cout << "Base 析构\n"; }
};
class Derived : public Base {
public:
Derived() { std::cout << "Derived 构造\n"; }
~Derived() { std::cout << "Derived 析构\n"; }
};
int main() {
Derived d;
return 0;
}典型输出顺序:Base 构造 → Derived 构造 → Derived 析构 → Base 析构。创建时先基类后派生;销毁时相反,见析构函数。
派生类构造函数与基类
若基类无默认构造,派生类须在初始化列表中显式调用基类构造函数:
class Base {
public:
explicit Base(int x) : x_(x) {}
private:
int x_;
};
class Derived : public Base {
public:
Derived(int x, int y) : Base(x), y_(y) {}
private:
int y_;
};名字隐藏
派生类声明与基类同名的成员函数会隐藏基类所有同名重载,而非自动形成覆盖。若要多态覆盖须使用 virtual 与 override,见多态与虚函数。若仅需引入基类重载,可写:
using Animal::speak;对象切片(slicing)
将派生类对象按值赋给基类对象时,派生部分被截断,只保留基类子对象:
Dog d;
Animal a = d; // 切片:a 仅是 Animal 部分需要多态行为时应使用基类指针或引用,或 std::unique_ptr<Base> 指向派生对象。
多重继承(入门)
C++ 允许从多个基类继承;菱形继承与虚基类属进阶主题。设计时优先组合(has-a)而非过深继承树,与封装原则一致。
本节说明了 public 继承与构造顺序。下一节介绍多态与虚函数:动态绑定与 override。