C++多态的实现

多态的实现

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. 虚函数机制被激活的条件
  1. 基类要定义虚函数
  2. 派生要重定义(覆盖)基类虚函数
  3. 创建派生类对象
  4. 基类指针指向派生类对象(引用)
  5. 通过基类指针(引用)调用虚函数
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;
}

多基派生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值