当一个类中有虚函数时,编译器会在这个类的对象中生成一个虚函数表,表中存储着虚函数的地址。当这个类产生派生类并且派生类中也定义了虚函数时,这个派生类会继承父类的虚函数表,然后在自己的虚函数表中添加自己的虚函数或者重载父类中的虚函数,这个过程叫做动态联编。
使用虚函数可以实现多态,多态可以让不同的子类对象调用相同的虚函数,实现统一的行为表现,提高了代码的复用性和维护性。
下面分别用两条示例说明虚函数实现多态的原理。
示例一:
#include <iostream>
using namespace std;
class Animal{
public:
virtual void speak(){
cout << "动物在说话" << endl;
}
};
class Cat : public Animal{
public:
void speak(){
cout << "小猫在说话" << endl;
}
};
class Dog : public Animal{
public:
void speak(){
cout << "小狗在说话" << endl;
}
};
int main()
{
Animal *animal1;
Cat cat1;
Dog dog1;
animal1 = &cat1;
animal1->speak();
animal1 = &dog1;
animal1->speak();
return 0;
}
示例说明:
- 定义了一个动物类,其中speak虚函数在子类中被重载。
- 定义了两个子类,分别是猫和狗,这两个子类都重载了speak函数。
- 在主函数中创建了一个动物指针类型的指针变量,animal1。
- 首先将这个指针指向猫对象cat1,调用animal1->speak()函数,此时输出“小猫在说话”。
- 然后将这个指针指向狗对象dog1,再次调用animal1->speak()函数,此时输出“小狗在说话”。
原因分析:
- 通过animal1指针指向不同的对象,虽然调用的函数名称相同,但却实现了不同的行为,实现了多态。
- 在当下的编译器实现中,调用函数时,首先查找使用virtual关键字定义的函数,如果没有找到虚函数,则使用重载过的函数,如果还没有找到,则找到与函数名称相同的函数。
示例二:
#include <iostream>
using namespace std;
class Parent{
public:
int num;
virtual void func(){
cout << "This is Parent's func" << endl;
}
};
class Child : public Parent{
public:
int num;
void func(){
cout << "This is Child's func" << endl;
}
};
int main()
{
Parent *pParent = new Child();
pParent->num = 1; // 父类中num的值
static_cast<Child *>(pParent)->num = 2; // 子类中num的值
cout << "num in Parent: " << pParent->num << endl;
cout << "num in Child: " << static_cast<Child *>(pParent)->num << endl;
pParent->func(); // 多态,调用子类中重载的虚函数
delete pParent;
return 0;
}
示例说明:
- 定义了一个父类,其中定义了一个变量num和一个虚函数func。
- 定义了一个子类,也包含了一个变量num和一个重载了虚函数func的同名函数。
- 在主函数中通过一个Parent指针指向一个Child对象,这个过程中实现了向上转型。同时,在对Parent指针类型变量进行操作时,会使用父类中的变量和函数。
- 通过static_cast强制类型转换获取Child对象中的num值进行操作。
- 调用pParent指针类型变量的func函数,这里实现了多态。
原因分析:
- pParent通过指向子类对象实现了向上转型,实现了父类指针指向子类对象的行为表现。
- 使用Cast操作符将parent类型的指针转化为指向子类对象的child类型的指针,实现了对子类对象中num变量的操作。
- 多态中使用的是编译器查找虚函数的方式,调用的是子类中重载的虚函数。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++语言中虚函数实现多态的原理详解 - Python技术站