C++之类内存布局实例演示④---补充(14)《Effective C++》

来源:互联网 发布:重新激活免费网络通信 编辑:程序博客网 时间:2024/06/13 22:22

1)针对多重继承中的虚函数而言,如果子类中没有重写多个父类中共有的virtual方法,看看关于子类的vfptr到底是父类中哪个的???

#include <iostream>using namespace std;class Base1{private:    int i;public:    Base1(int i) :i(i=10){    }    virtual void show(){        cout << "Base1:" << this->i << endl;    }    virtual ~Base1(){        cout << "Base1析构开始。。。" << endl;    }};class Base2{private:    int j;public:    Base2(int j) :j(j = 20){    }    virtual void show(){        cout << "Base2:" << this->j << endl;    }    virtual ~Base2(){        cout << "Base2析构开始。。。" << endl;    }};class Derived :public Base1, public Base2{private:    int k;public:    Derived(int i, int j, int k) :Base1(i), Base2(j), k(k){    }    /*virtual void show(){        cout << "Derived:" << k << endl;    }*/    virtual ~Derived(){        cout << "Derived析构开始。。。" << endl;    }};int main(){    Base1* b1 = new Derived(1, 2, 3);    b1->show();    Base2* b2 = new Derived(4, 5, 6);    b2->show();    delete b1;    delete b2;    return 0;}

运行结果:
炜炜一笑很倾城

结果表明,当子类没有对多个父类共有的virtual方法进行重写时候,子类中的vfptr可能会有多个,那么子类调用的时候到底调用哪个呢?运行结果告诉我们适合哪个就调用哪个啦,哈哈哈!

2)多个父类的共有的virtual函数在子类中被进行了重写,那么子类中的vfptr也会有多个,同样的需要调用哪个呢?

#include <iostream>using namespace std;class Base1{private:    int i;public:    Base1(int i) :i(i=10){    }    virtual void show(){        cout << "Base1:" << this->i << endl;    }    virtual ~Base1(){        cout << "Base1析构开始。。。" << endl;    }};class Base2{private:    int j;public:    Base2(int j) :j(j = 20){    }    virtual void show(){        cout << "Base2:" << this->j << endl;    }    virtual ~Base2(){        cout << "Base2析构开始。。。" << endl;    }};class Derived :public Base1, public Base2{private:    int k;public:    Derived(int i, int j, int k) :Base1(i), Base2(j), k(k){    }    virtual void show(){        cout << "Derived:" << k << endl;    }    virtual ~Derived(){        cout << "Derived析构开始。。。" << endl;    }};int main(){    Base1* b1 = new Derived(1, 2, 3);    b1->show();    Base2* b2 = new Derived(4, 5, 6);    b2->show();    delete b1;    delete b2;    return 0;}

运行结果:
炜炜一笑很倾城

看到结果你就明白啦,这是一种优化体系,所以,Derived重写部分的东西会出现在Derived中的第一个vfptr指向的虚函数表后面,因此,调用的肯定为第一个vfptr指向的虚函数表啦(内存结构②中有相应的图示,可以仔细研究一下)~~~
注意这种结构中,Derived class中的内存布局,里面有两个vfptr指针,vfptr中指向的show()函数都是&Derived::show(),所以无论我们怎样调用都会调用的是Derived::show(),所以被重载啦!!!

3)针对虚继承,我们可以进行如下探索:

#include <iostream>using namespace std;class Base{public:    virtual void show() = 0;};class Base1:virtual public Base{private:    int i;public:    Base1(int i) :i(i=10){    }    virtual void show(){        cout << "Base1:" << this->i << endl;    }    virtual ~Base1(){        cout << "Base1析构开始。。。" << endl;    }};class Base2:virtual public Base{private:    int j;public:    Base2(int j) :j(j = 20){    }    virtual void show(){        cout << "Base2:" << this->j << endl;    }    virtual ~Base2(){        cout << "Base2析构开始。。。" << endl;    }};class Derived :public Base1, public Base2{private:    int k;public:    Derived(int i, int j, int k) :Base1(i), Base2(j), k(k){    }    virtual void show(){        cout << "哈哈哈哈,发生了什么,我为什么一定要出现啊???" << endl;    }    virtual ~Derived(){        cout << "Derived析构开始。。。" << endl;    }};int main(){    Base1* b1 = new Derived(1, 2, 3);    b1->show();    Base2* b2 = new Derived(4, 5, 6);    b2->show();    delete b1;    delete b2;    return 0;}

运行结果:
炜炜我爱你

结果可以发现,虚继承确保基类在其菱形子类中的数据只会出现一份,所以,上例中Derived::show()必须重写,因为不重写的话C++不知道究竟需要调用哪种。。。
具体可以参考:C++内存分布(带有虚继承)—补充(11)《Effective C++》

原创粉丝点击