C++ 多态学习笔记

多态是C++中面向对象编程中的重要概念之一。它允许我们使用基类类型的指针或引用调用派生类对象的方法,从而实现了同一接口的不同实现。

多态的实现方式

虚函数

在C++中,多态最常见的实现方式就是通过虚函数来实现。虚函数是在基类中声明的函数,在派生类中可以进行重写,从而实现不同的行为。当我们使用基类指针或引用调用派生类对象的虚函数时,会根据实际对象的类型调用对应的函数。

c++Copy Code
class Shape { public: virtual void draw() { std::cout << "Drawing a shape\n"; } }; class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle\n"; } }; class Square : public Shape { public: void draw() override { std::cout << "Drawing a square\n"; } }; int main() { std::vector<Shape*> shapes; shapes.push_back(new Circle()); shapes.push_back(new Square()); for (auto shape : shapes) { shape->draw(); } return 0; }

上面的代码定义了一个基类Shape和两个派生类Circle和Square,它们都重写了基类中的虚函数draw。接下来我们创建了两个不同的对象,并将它们存储在一个基类指针数组中。在循环中,我们通过基类指针调用每个对象的虚函数draw,这时会根据实际对象的类型,调用对应的函数。

纯虚函数

有时候,我们需要在基类中声明虚函数,但是希望派生类必须对其进行实现。这时就可以使用纯虚函数来实现。纯虚函数是在基类中声明的虚函数,但是没有实现,需要在派生类中进行实现。如果一个类中拥有纯虚函数,则该类称为抽象类,不能进行实例化。

c++Copy Code
class Shape { public: virtual void draw() = 0; }; class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle\n"; } }; int main() { // Shape shape; // 错误,无法实例化抽象类 Circle circle; circle.draw(); return 0; }

上面的代码定义了一个抽象类Shape和一个派生类Circle,它们都实现了虚函数draw。由于Shape中的draw是纯虚函数,所以无法进行实例化。而Circle中的draw重写了Shape中的draw,使得Circle可以进行实例化并调用draw函数。

多态的使用场景

多态能够提高代码的可扩展性和可维护性,使得代码更加灵活,更容易适应变化。常见的使用场景包括但不限于:

  • 实现类似于插件的机制,让程序可以动态地加载和卸载不同的功能模块。
  • 在模板方法中,让子类可以根据实际情况来实现模板的具体行为。
  • 对于消息分发、事件处理等场景,可以使用多态来实现不同类型的消息或事件的处理。

实例

下面我们来看一个更具体的例子。

c++Copy Code
class Animal { public: virtual void speak() = 0; }; class Dog : public Animal { public: void speak() override { std::cout << "汪汪汪\n"; } }; class Cat : public Animal { public: void speak() override { std::cout << "喵喵喵\n"; } }; void communicate(Animal* animal) { animal->speak(); } int main() { Dog dog; Cat cat; communicate(&dog); communicate(&cat); return 0; }

上面的代码定义了一个抽象类Animal和两个派生类Dog和Cat,它们都实现了虚函数speak。接下来我们定义了一个函数communicate,它的参数类型是Animal的指针。在communicate函数中,我们调用了animal的speak方法,这时会根据实际对象的类型,调用对应的函数。在主函数中,我们创建了一个Dog对象和一个Cat对象,并分别将它们传递给communicate函数,从而实现了不同类型的动物的交流。