==============================
[6] Derive.iderive = 100
*/?
(3)重复继承
下面我们再来看看,发生重复继承的情况。所谓重复继承,也就是某个基类被间接地重复继承了多次。
下图是一个继承图,我们重载了父类的f()函数。
?
?
?
下面是对于子类实例中的虚函数表的图:
?
?
?
我们可以看见,最顶端的父类B其成员变量存在于B1和B2中,并被D给继承下去了。而在D中,其有B1和B2的实例,于是B的成员在D的实例中存在两份,一份是B1继承而来的,另一份是B2继承而来的。所以,如果我们使用以下语句,则会产生二义性编译错误:
?
?
?
void test_error()
{
? ? D d;
? ? // d.ib = 1; ? ?//ERROR
? ? d.B1::ib = 1; ? // ok
? ? d.B2::ib = 100; // ok
}
注意,上面例程中的最后两条语句存取的是两个变量。虽然我们消除了二义性的编译错误,但B类在D中还是有两个实例,这种继承造成了数据的重复,我们叫这种继承为重复继承。重复的基类数据成员可能并不是我们想要的。所以,
C++引入了虚基类的概念。?
?
代码验证如下
?
?
?
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/9/29
*/
?
#include "stdafx.h"
#include
using namespace std;
?
?
class B
{
public:
? ? int ib;
? ? char cb;
public:
? ? B(): ib(0), cb('B') {}
?
? ? virtual void f()
? ? {
? ? ? ? cout << "B::f()" << endl;
? ? }
? ? virtual void Bf()
? ? {
? ? ? ? cout << "B::Bf()" << endl;
? ? }
};
?
class B1 : ?public B
{
public:
? ? int ib1;
? ? char cb1;
public:
? ? B1(): ib1(11), cb1('1') {}
?
? ? virtual void f()
? ? {
? ? ? ? cout << "B1::f()" << endl;
? ? }
? ? virtual void f1()
? ? {
? ? ? ? cout << "B1::f1()" << endl;
? ? }
? ? virtual void Bf1()
? ? {
? ? ? ? cout << "B1::Bf1()" << endl;
? ? }
?
};
?
class B2: ?public B
{
public:
? ? int ib2;
? ? char cb2;
public:
? ? B2(): ib2(12), cb2('2') {}
?
? ? virtual void f()
? ? {
? ? ? ? cout << "B2::f()" << endl;
? ? }
? ? virtual void f2()
? ? {
? ? ? ? cout << "B2::f2()" << endl;
? ? }
? ? virtual void Bf2()
? ? {
? ? ? ? cout << "B2::Bf2()" << endl;
? ? }
?
};
?
class D : public B1, public B2
{
public:
? ? int id;
? ? char cd;
public:
? ? D(): id(100), cd('D') {}
?
? ? virtual void f()
? ? {
? ? ? ? cout << "D::f()" << endl;
? ? }
? ? virtual void f1()
? ? {
? ? ? ? cout << "D::f1()" << endl;
? ? }
? ? virtual void f2()
? ? {
? ? ? ? cout << "D::f2()" << endl;
? ? }
? ? virtual void Df()
? ? {
? ? ? ? cout << "D::Df()" << endl;
? ? }
?
};
?
typedef void(*Fun)(void);
?
?
void test_error()
{
? ? D d;
? ? // d.ib = 1; ? ?//ERROR
? ? d.B1::ib = 1; ? // ok
? ? d.B2::ib = 100; // ok
}
?
/*
B1.vptr --->D::f,B::Bf,D::f1,B1::Bf1,D::Df
B.ib
B.cb
B1.ib1
B1.cb1
?
B2.vptr --->D::f,B::Bf,D::f2,B2::Bf2
B.ib
B.cb
B2.ib2
B2.cb2
?
D.id
D.cd
*/
void test_public()
{
? ? D obj;
? ? Fun pFun;
? ? int **pVtab = (int **)(&obj);
?
? ? int n = 5;
? ? cout << "[0] D::B1::_vptr->" << endl;
? ? for (int i = 0; i < n; i++)
? ? {
? ? ? ? pFun = (Fun)pVtab[0][i];
? ? ? ? cout << "------[" << i << "] ";
? ? ? ? pFun();
? ? }
? ? cout << "[1] B.ib = " << (int)pVtab[1] << endl;
? ? cout << "[2] B.cb = " << (char)pVtab[2] << endl;
? ? cout << "[3] B1.ib1 = " << (int)pVtab[3] << endl;
? ? cout << "[4] B1.cb1 = " << (char)pVtab[4] << endl;
?
? ? n = 4;
? ? cout << "[5] D::B2::_vptr->" << endl;
? ? for (int i = 0; i < n; i++)
? ? {
? ? ? ? pFun = (Fun)pVtab[5][i];
? ? ? ? cout << "------[" << i << "] ";
? ? ? ? pFun();
? ? }
? ? cout << "[6] B.ib = " << (int)pVtab[6] << endl;
? ? cout << "[7] B.cb = " << (char)pVtab[7] << endl;
? ? cout << "[8] B2.ib2 = " << (int)pVtab[8] << endl;
? ? cout << "[9] B2.cb2 = " << (char)pVtab[9] << endl;
?
? ? cout << "[10] D.id = " << (int)pVtab[10] << endl;
? ? cout << "[11] D.cd = " << (char)pVtab[11] << endl;
}
?
void test_virtual_public()
{
?
}
?
int main()
{
? ? test_public();
? ? return 0;
}
/*
[0] D::B1::_vptr->
------[0] D::f()
------[1] B::Bf()
------[2] D::f1()
------[3] B1::Bf1()
------[4] D::Df()
[1] B.ib = 0
[2] B.cb = B
[3] B1.ib1 = 11
[4] B1.cb1 = 1
[5] D::B2::_vptr->
------[0] D::f()
------[1] B::Bf()
------[2] D::f2()
------[3] B2::Bf2()
[6] B.ib = 0
[7] B.cb = B
[8] B2.ib2 = 12
[9] B2.cb2 = 2
[10] D.id = 100
[11] D.cd = D
*/