一、继承机制:代码复用的基石
1.1 继承的概念与本质
继承是面向对象编程中实现代码复用的核心机制,它允许一个类(派生类)获取另一个类(基类)的成员变量和成员函数。这种关系类似于现实世界中的 "is-a" 关系,例如 "狗是一种动物"。
在 C++ 中,继承通过类定义时的冒号语法实现:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Animal { public: void speak() { std::cout << "The animal makes a sound." << std::endl; } };
class Dog : public Animal { public: void bark() { std::cout << "The dog barks." << std::endl; } };
|
在上述示例中,Dog 类继承自 Animal 类,Dog 类的对象不仅可以调用自己的 bark 函数,还能调用从 Animal 类继承而来的 speak 函数。继承的本质是创建新的数据类型,该类型自动包含基类的特性,并可添加新特性或修改已有特性。
1.2 访问控制与继承方式
C++ 提供三种访问控制符,用于控制基类成员在派生类中的可见性:
public(公有):基类的公有成员在派生类中仍为公有
protected(保护):基类的保护成员在派生类中仍为保护
private(私有):基类的私有成员在派生类中不可直接访问
同时,继承方式也有三种:
以 public 继承为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Base { public: int publicMember; protected: int protectedMember; private: int privateMember; };
class Derived : public Base { public: void accessMembers() { publicMember = 10; // 合法,基类公有成员在派生类中仍为公有 protectedMember = 20; // 合法,基类保护成员在派生类中仍为保护 // privateMember = 30; // 非法,基类私有成员在派生类中不可直接访问 } };
|
1.3 继承层次结构
单继承是指一个派生类仅从一个基类继承,形成简单的线性关系。多继承则允许一个派生类从多个基类继承,能组合多个类的特性,但可能导致 "菱形继承" 问题(同一个基类被间接继承多次)。
解决菱形继承问题的方法是使用虚继承:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class A { public: int sharedData; };
class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C {};
int main() { D d; d.sharedData = 10; // 通过虚继承,避免二义性,可直接访问 return 0; }
|
虚继承确保派生类中只保留一份基类成员的拷贝,避免二义性。
二、多态机制:接口与实现的分离
2.1 多态的概念与分类
多态是指同一接口的不同实现,在 C++ 中主要分为:
运行时多态是面向对象编程的核心特性,它允许程序在不了解对象具体类型的情况下,通过基类接口调用正确的派生类实现。
2.2 虚函数与动态绑定
虚函数是在基类中声明为 virtual 的成员函数,派生类可以重写(override)这些函数。当通过基类指针或引用调用虚函数时,会根据对象的实际类型调用相应的版本,这一过程称为动态绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Shape { public: virtual void draw() { std::cout << "Drawing a generic shape." << std::endl; } };
class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle." << std::endl; } };
class Rectangle : public Shape { public: void draw() override { std::cout << "Drawing a rectangle." << std::endl; } };
int main() { Shape* shapes[2]; shapes[0] = new Circle(); shapes[1] = new Rectangle();
for (int i = 0; i < 2; ++i) { shapes[i]->draw(); // 根据对象实际类型调用相应的draw函数 delete shapes[i]; }
return 0; }
|
override 关键字(C++11 引入)显式指明函数重写基类虚函数,有助于编译器检查错误。
2.3 纯虚函数与抽象类
纯虚函数是没有实现的虚函数,声明方式为在函数原型后加 = 0:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Shape { public: virtual void draw() = 0; // 纯虚函数 };
class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle." << std::endl; } };
class Rectangle : public Shape { public: void draw() override { std::cout << "Drawing a rectangle." << std::endl; } };
|
包含纯虚函数的类称为抽象类,抽象类不能实例化,只能作为基类被继承。派生类必须实现所有纯虚函数才能成为可实例化的具体类。
抽象类的主要作用是定义接口,强制派生类实现特定功能,体现 "接口重用" 的设计思想。