多态的实现
1. 虚函数的实现原理
如果类中包含有虚成员函数,在用该类实例化对象时,对象的存储布局之中会产生一个虚函数指针(vfptr),该虚函数指针指向一张虚函数表(vftable),虚函数表里面存放的是虚函数的入口地址。
如上图所示,通过virtual关键字使得派生类覆盖display()方法,此时的派生类的虚表存储的是派生类display()的入口地址,让基类的指针指向派生类对象,而派生类对象虚函数指针指向的虚表存储着display()的入口地址,这就可以实现多态。
//Base类
virtual void display() const
{
cout << "Base::display()" << endl;
}
//Derived类
virtual void dislay() const
{
cout << "Derived::display()" << endl;
}
//全局display()
void display(Base* base)
{
base.display();
}
int main()
{
Base base;
Derived derived;
display(&base);//调用基类display()
display(&derived);//调用派生类display()
}
2. 虚函数机制被激活的条件
- 基类要定义虚函数
- 派生要重定义(覆盖)基类虚函数
- 创建派生类对象
- 基类指针指向派生类对象(引用)
- 通过基类指针(引用)调用虚函数
3. 为什么构造函数不能设为虚函数
根据虚函数被激活的条件,先要创建对象,才会生成虚函数指针,之后才能使用虚函数
4. 虚函数之析构函数
- 当创建了指向堆对象的指针后,若没有将基类的析构函数设为虚函数,此时派生类的指针无法释放,造成内存泄漏。
- 只要将基类的析构函数设为虚函数,派生类的析构函数会自动成为虚函数
- 只要类中出现了虚函数,都要讲析构函数设为虚函数
#include <iostream>
using std::cout;
using std::endl;
class Base
{public:
Base()
: _pdata(new int(0))
{ cout << "Base()" << endl; }
virtual void display() const
{
cout << "Base::display() *_pdata = " << *_pdata << endl;
}
virtual
~Base()
{
cout << "~Base()" << endl;
delete _pdata;
}
private:
int * _pdata;
};
class Derived
: public Base
{public:
Derived(int data)
: Base()
, _pdata2(new int(data))
{ cout << "Derived(int)" << endl; }
//只要将基类的析构函数设置成虚函数之后,派生类析构函数自动成为虚函数
~Derived()
{
cout << "~Derived()" << endl;
delete _pdata2;
}
private:
int * _pdata2;
};
int main(void)
{
Base * pbase = new Derived(100);
pbase->display();
delete pbase;
return 0;
}
5. 多基派生二义性
#include <iostream>using std::cout;
using std::endl;
class A
{public:
virtual void a() { cout << "A::a()" << endl; }
virtual void b() { cout << "A::b()" << endl; }
virtual void c() { cout << "A::c()" << endl; }};
class B
{public:
virtual void a() { cout << "B::a()" << endl; }
virtual void b() { cout << "B::b()" << endl; }
void c() { cout << "B::c()" << endl; }
void d() { cout << "B::d()" << endl; }};
class C
: public A
, public B
{public:
virtual void a() { cout << "C::a()" << endl; }
void c() { cout << "C::c()" << endl; }
void d() { cout << "C::d()" << endl; }};
int main(void)
{
A a;
B b;
C c;
A * pA = &c;
cout << "pA = " << pA << endl;
pA->a();//C::a()
pA->b();//A::b()
pA->c();//C::c()
cout << endl;
B * pB = &c;
cout << "pB = " << pB << endl;
pB->a();//C::a()
pB->b();//B::b()
pB->c();//B::b()
pB->d();//B::d()
cout << endl;
C * pC = &c;
cout << "pC = " << pC << endl;
pC->a();//C::a()
//pC->b();//error二义性
pC->A::b();
pC->B::b();
pC->c();//C::c()
pC->d();//C::d()
return 0;
}