在C++中,继承
和接口
(通常通过抽象类实现)是面向对象编程的重要特性。它们使得代码复用和多态成为可能。尽管这些概念在基础教程中已经有所介绍,但在实际应用中有很多高级技巧和设计模式,这些技巧能帮助我们设计出更加灵活和可维护的程序。
1. 继承的深度应用
1.1. 继承的类型
在C++中,继承主要有三种类型:
公有继承
(public inheritance)
保护继承
(protected inheritance)
私有继承
(private inheritance)
公有继承是最常用的类型。它表示“是一个”的关系。假如有一个Base
类和一个Derived
子类,使用公有继承,Derived
类将继承Base
类的接口和实现。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Base { public: void show() { std::cout << "Base class method" << std::endl; } };
class Derived : public Base { public: void display() { std::cout << "Derived class method" << std::endl; } };
|
1.2. 虚继承
在多重继承中,出现菱形继承
问题,即同一个基类可能被多个派生类多次继承,这会导致基类的成员在最终派生类中出现多次。一种解决方案是使用虚继承
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Base { public: Base() { std::cout << "Base constructor" << std::endl; } };
class Intermediate1 : virtual public Base { public: Intermediate1() { std::cout << "Intermediate1 constructor" << std::endl; } };
class Intermediate2 : virtual public Base { public: Intermediate2() { std::cout << "Intermediate2 constructor" << std::endl; } };
class Final : public Intermediate1, public Intermediate2 { public: Final() { std::cout << "Final constructor" << std::endl; } };
int main() { Final f; return 0; }
|
2. 接口的设计与实现
2.1. 抽象类与纯虚函数
在C++中,通过抽象类
和纯虚函数
来定义接口。抽象类不能被实例化,而其派生类必须实现所有的纯虚函数。
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
| class IShape { public: virtual void draw() = 0; virtual double area() = 0; };
class Circle : public IShape { public: void draw() override { std::cout << "Drawing Circle" << std::endl; } double area() override { return 3.14 * radius * radius; } };
class Square : public IShape { public: void draw() override { std::cout << "Drawing Square" << std::endl; } double area() override { return side * side; } };
|
2.2. 多态和容器
使用接口
和多态
可以设计灵活的系统。我们可以用智能指针
和容器
来管理实现了接口的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream> #include <vector> #include <memory>
void drawShapes(const std::vector<std::shared_ptr<IShape>>& shapes) { for (const auto& shape : shapes) { shape->draw(); } }
int main() { std::vector<std::shared_ptr<IShape>> shapes; shapes.push_back(std::make_shared<Circle>()); shapes.push_back(std::make_shared<Square>()); drawShapes(shapes); return 0; }
|
3. 设计模式中的继承与接口
3.1. 策略模式
在策略模式中,我们通过接口
定义一系列算法,并让具体的算法类实现这个接口,使得算法可以互换。
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
| class SortingStrategy { public: virtual void sort(std::vector<int>& data) = 0; };
class BubbleSort : public SortingStrategy { public: void sort(std::vector<int>& data) override { } };
class QuickSort : public SortingStrategy { public: void sort(std::vector<int>& data) override { } };
class Context { SortingStrategy* strategy; public: void setStrategy(SortingStrategy* strat) { strategy = strat; }
void sortData(std::vector<int>& data) { strategy->sort(data); } };
|
3.2. 观察者模式
在观察者模式中,接口
可以定义观察者和被观察者的交互规则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Observer { public: virtual void update() = 0; };
class Subject { std::vector<Observer*> observers; public: void attach(Observer* obs) { observers.push_back(obs); } void notifyAll() { for (auto& obs : observers) { obs->update(); } } };
|
4. 总结
通过继承
和接口
的高级应用,我们可以设计出具有灵活性和可扩展性的系统。掌握这些概念将使我们能够更好地应对复杂的编程问题,提高代码的重用性和可维护性。希望本节内容能帮助你在C++中深入理解和应用继承
与接口
的特性。