在C++中,多态是一种面向对象编程的重要概念,它允许使用基类指针或引用来调用派生类对象的成员函数。多态性是通过虚函数和纯虚函数来实现的。在本文中,我们将详细介绍C++中多态的实现方式。
虚函数是一种特殊的成员函数,它可以在派生类中被重写。当使用基类指针或引用调用虚函数时,将根据指针或引用所指向的对象的实际类型来调用相应的函数。这种行为称为动态绑定或后期绑定。
在C++中,将函数声明为虚函数的方式是在函数声明前加上关键字virtual
。例如:
class Shape {
public:
virtual void draw() {
// ...
}
};
class Circle : public Shape {
public:
void draw() override {
// ...
}
};
在上面的代码中,Shape
类中的draw()
函数被声明为虚函数。Circle
类中的draw()
函数重写了Shape
类中的draw()
函数。注意,override
关键字是C++11中的新特性,它用于显式地指示函数是重写基类中的虚函数。
虚函数表是一种数据结构,它存储了每个类的虚函数的地址。每个对象都有一个指向其类的虚函数表的指针。当调用虚函数时,程序将使用该指针来查找虚函数表,并调用适当的函数。
虚函数表是由编译器生成的,它在程序运行时被加载到内存中。每个类都有一个虚函数表,其中包含该类的虚函数的地址。虚函数表的第一个条目是一个指向该类的类型信息的指针。这个指针用于在运行时确定对象的类型。
当一个类声明了虚函数时,编译器会为该类生成一个虚函数表。虚函数表是一个包含虚函数地址的数组,每个虚函数在表中占据一个位置。每个对象都有一个指向其类的虚函数表的指针,该指针在对象创建时被初始化。当调用虚函数时,程序将使用该指针来查找虚函数表,并调用适当的函数。
例如,假设我们有以下代码:
Shape* shape = new Circle();
shape->draw();
在上面的代码中,我们创建了一个Circle
对象,并将其赋值给一个Shape
指针。然后,我们调用draw()
函数。由于draw()
函数是虚函数,程序将使用shape
指针中存储的虚函数表来查找Circle
类中的draw()
函数的地址,并调用该函数。
纯虚函数是一种没有实现的虚函数。它的声明以= 0
结尾。纯虚函数的目的是为了让派生类必须实现该函数。如果一个类中包含纯虚函数,则该类被称为抽象类,不能创建该类的对象。
例如,假设我们有以下代码:
class Shape {
public:
virtual void draw() = 0;
};
class Circle : public Shape {
public:
void draw() override {
// ...
}
};
在上面的代码中,Shape
类中的draw()
函数被声明为纯虚函数。由于Shape
类中包含纯虚函数,因此不能创建Shape
类的对象。Circle
类重写了Shape
类中的draw()
函数,因此可以创建Circle
类的对象。