深入解析C++继承机制:从基础到多态实现
🔗 运行环境:C/C++
🚩 撰写作者:左手の明天
🥇 精选专栏:《python》
🔥 推荐专栏:《算法研究》
🔐#### 防伪水印——左手の明天 ####🔐
💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗
💗今天分享【C/C++】——继承💗
📆 最近更新:2025 年 03 月 30 日,左手の明天的第 356 篇原创博客
📚 更新于专栏:C/C++入门与进阶
🔐#### 防伪水印——左手の明天 ####🔐
一、继承基础概念
1.1 继承的本质
继承是面向对象编程的三大特性之一,允许子类继承父类的属性和方法,简单地说,派生类是基类得一种特殊化,它继承了基类的成员变量和成员函数,并且可以在这个基础上添加新的成员或者修改从基类继承来的成员的行为,实现代码复用和层次化设计。
// 基类定义
class Animal {
public:
void breathe() {
cout << "呼吸中..." << endl;
}
int age;
};
// 派生类定义
class Dog : public Animal { // 公有继承
public:
void bark() {
cout << "汪汪!" << endl;
}
};
// 使用示例
int main() {
Dog myDog;
myDog.breathe(); // 继承基类方法
myDog.bark(); // 自身方法
myDog.age = 2; // 继承基类属性
}
二、继承类型详解
2.1 三种继承方式对比
继承分为public、protected、private;这几种继承方式的不同体现在子类中对父类属性或者行为的访问权限:
继承方式 | 基类public成员 | 基类protected成员 | 基类private成员 |
---|---|---|---|
public | public | protected | 不可访问 |
protected | protected | protected | 不可访问 |
private | private | private | 不可访问 |
- 子类不能在类外或者类内直接访问父类的private属性或者行为;无论是哪种访问限定符修饰的属性或者行为,但是父类的行为和属性还是被继承到子类中了;
- protected继承:父类中的public或者protected访问限定符修饰的在子类中的访问权限全部变为protected;若是想父类中的不被类外部访问,但是想要被子类访问,就把父类中的属性或者行为的访问限定符写作protected;可以得知protected就是为了继承而生的;
- 继承时可以不写继承的方式。那么class默认为private继承;struct默认为pubilc继承;
2.2 代码示例
class Base {
public:
int publicVar = 1;
protected:
int protectedVar = 2;
private:
int privateVar = 3;
};
// 公有继承
class PublicDerived : public Base {
void accessCheck() {
publicVar = 10; // ✔️ 保持public
protectedVar = 20; // ✔️ 保持protected
// privateVar = 30; // ❌ 不可访问
}
};
// 保护继承
class ProtectedDerived : protected Base {
void accessCheck() {
publicVar = 10; // ✔️ 转为protected
protectedVar = 20; // ✔️ 保持protected
}
};
// 私有继承
class PrivateDerived : private Base {
void accessCheck() {
publicVar = 10; // ✔️ 转为private
protectedVar = 20; // ✔️ 转为private
}
};
三、继承中的构造/析构机制
3.1 执行顺序
基类构造 -> 派生类构造 -> 派生类析构 -> 基类析构
class BaseClass {
public:
BaseClass() { cout << "基类构造" << endl; }
~BaseClass() { cout << "基类析构" << endl; }
};
class DerivedClass : public BaseClass {
public:
DerivedClass() { cout << "派生类构造" << endl; }
~DerivedClass() { cout << "派生类析构" << endl; }
};
/*
输出顺序:
基类构造 -> 派生类构造 -> 派生类析构 -> 基类析构
*/
3.2 初始化列表实践
class Engine {
public:
Engine(int hp) : horsepower(hp) {}
private:
int horsepower;
};
class Car : public Engine {
public:
// 正确初始化基类成员
Car(int hp, string c) : Engine(hp), color(c) {}
private:
string color;
};
四、多态与虚函数
4.1 虚函数实现动态绑定
class Shape {
public:
virtual void draw() { // 虚函数声明
cout << "绘制基础形状" << endl;
}
virtual ~Shape() {} // 虚析构函数
};
class Circle : public Shape {
public:
void draw() override { // 方法重写
cout << "绘制圆形" << endl;
}
};
class Square : public Shape {
public:
void draw() override {
cout << "绘制正方形" << endl;
}
};
// 多态调用演示
void drawShape(Shape& shape) {
shape.draw();
}
int main() {
Circle c;
Square s;
drawShape(c); // 输出:绘制圆形
drawShape(s); // 输出:绘制正方形
}
五、多重继承与虚继承
5.1 多重继承示例
class Printer {
public:
void print(string doc) {
cout << "打印文档: " << doc << endl;
}
};
class Scanner {
public:
void scan() {
cout << "扫描文档" << endl;
}
};
// 多重继承
class AllInOne : public Printer, public Scanner {};
// 使用
AllInOne device;
device.print("报告");
device.scan();
5.2 虚继承解决菱形问题
class BaseComponent {
public:
int id;
};
// 虚继承声明
class Mouse : virtual public BaseComponent {};
class Keyboard : virtual public BaseComponent {};
class InputDevice : public Mouse, public Keyboard {
public:
void setup() {
id = 100; // 现在不会产生二义性
}
};
六、最佳实践与常见陷阱
6.1 继承使用准则
-
优先使用组合而非继承
-
保持继承层次不超过3层
-
基类析构函数必须为虚函数
-
避免多重继承的复杂层级
6.2 常见错误示例
class A {
private:
int secret;
};
class B : public A {
public:
void expose() {
// cout << secret; // 错误:访问基类私有成员
}
};
class C {
public:
void func();
};
class D : public C {
private:
using C::func; // 改变访问权限
};
七、现代C++继承特性
7.1 override/final关键字
class Base {
public:
virtual void process() {}
virtual void log() final {} // 禁止重写
};
class Derived : public Base {
public:
void process() override {} // 显式重写
// void log() {} // 错误:尝试重写final方法
};
7.2 使用智能指针管理继承
class Animal {
public:
virtual ~Animal() = default;
};
class Cat : public Animal {};
// 使用基类指针管理派生类对象
unique_ptr<Animal> pet = make_unique<Cat>();