C++中的多态(Polymorphism)

发布于:2024-05-21 ⋅ 阅读:(183) ⋅ 点赞:(0)

C++中的多态(Polymorphism)是面向对象编程的三大特性之一,它允许使用父类类型的指针或引用来指向子类对象,并通过该指针或引用来调用子类中覆盖或重载的方法,从而实现一种通用的、可重用的程序设计。

多态的实现主要依赖于以下机制:

  1. 虚函数(Virtual Functions)
    • 父类中声明为virtual的成员函数可以在子类中被覆盖(override)。
    • 当使用父类类型的指针或引用来指向子类对象时,通过该指针或引用来调用虚函数,会执行子类中覆盖的版本,而不是父类中的版本。
  2. 纯虚函数(Pure Virtual Functions)
    • 在虚函数的声明后加上= 0,则该函数变为纯虚函数。
    • 包含纯虚函数的类被称为抽象类(Abstract Class),它不能被实例化。
    • 派生自抽象类的子类必须提供纯虚函数的实现,除非该子类也是抽象类。
  3. 动态绑定(Dynamic Binding)
    • 也称为后期绑定或运行时绑定。
    • 在运行时,根据对象的实际类型来确定调用哪个版本的成员函数。
  4. 函数重载(Function Overloading)
    • 虽然函数重载与多态的概念不完全相同,但它是多态的一种表现形式。
    • 同一个类中可以存在多个同名但参数列表不同的成员函数,编译器根据调用时提供的参数来确定调用哪个版本的函数。
  5. 构造函数和析构函数不能是虚函数
    • 构造函数在对象被创建时调用,而析构函数在对象被销毁时调用。在这两个时间点,对象的类型已经确定,因此没有必要进行动态绑定。
    • 如果需要在析构时执行特定的操作,可以考虑将这部分操作放在一个虚函数中,并在析构函数中调用它。
  6. 多态与继承、封装的关系
    • 多态性是与继承紧密相关的,它是通过类的继承层次结构来实现的。
    • 封装则是将对象的属性和操作隐藏起来,只对外提供必要的接口。多态性可以看作是封装的一种延续,它使得我们可以使用统一的接口来处理不同的对象。

示例:


cpp复制代码

class Animal {
public:
virtual void speak() {
std::cout << "The animal speaks" << std::endl;
}
virtual ~Animal() {} // 虚析构函数,确保多态删除时正确调用子类的析构函数
};
class Dog : public Animal {
public:
void speak() override {
std::cout << "The dog barks" << std::endl;
}
};
class Cat : public Animal {
public:
void speak() override {
std::cout << "The cat meows" << std::endl;
}
};
void letAnimalSpeak(Animal* animal) {
animal->speak(); // 多态调用,执行的是实际对象(Dog或Cat)的speak方法
}
int main() {
Dog myDog;
Cat myCat;
letAnimalSpeak(&myDog); // 输出 "The dog barks"
letAnimalSpeak(&myCat); // 输出 "The cat meows"
return 0;
}