c++之中一个类不能被多次说明为一个派生类的直接基类,但可以多次成为间接基类。
一 非虚继承类
例子:
class B
{
public:
int x.....
}
class A1:public B
{
.....
}
class A2:public B
{
......
}
class D:public A1,public A2
{
......
}
可以看出,D类继承了A1和A2,而A1和A2继承了B ,也就是说D类有两个B类的成员副本,所以称B是非虚基类。
非虚继承测试:
#include<iostream>
using namespace std;
class B
{
public:
B()
{cout<<"construct called:B\n";}
~B()
{cout<<"destructor called:B\n";}
int b;
};
class B1:public B
{
public:
B1() {cout<<"constuct called:B1\n";}
~B1() {cout<<"destruct called:B1"<<endl;}
int b1;
};
class B2:public B
{
public:
B2() {cout<<"constuct called:B2\n";}
~B2() {cout<<"destruct called:B2"<<endl;}
int b2;
};
class D:public B1,public B2
{
public:
D() {cout<<"constuct called:D\n";}
~D() {cout<<"destruct called:D"<<endl;}
int d;
};
void test()
{
D dd;
dd.B1::b=5;
dd.B2::b=10;
dd.b1=25;
dd.b2=111;
dd.d=149;
cout<<"dd.B1::b="<<dd.B1::b<<"dd.B2::b"<<dd.B2::b<<"dd.b1="<<dd.b1<<"dd.b2="<<dd.b2<<"dd.b"<<dd.d<<endl;
}
int main()
{
test();
}
运行结果可以自己去试着运行看一下。
运行后第一轮输出的字符,如“construct called:B”等可以看出运行的顺序。
而void test()里面它直接用D dd,并且输出有d1,d2,d,b,而class D里只是定义了int d;所以显而易见是因为继承了B1和B2。还有要注意,为了访问不同版本的d,必须要用作用域指名是那个基类。
虚继承
当我们为了避免产生二义性,直接想用一个dd.b版本的时候,我们就需要把B1和B2对 B的继承说明为虚继承,它的说明形式是在类继承的关键字前面加一个virtual。这样就不用分别再建立dd.B1:: b,dd. B2::b,而是有virtual指引建立指向dd.b的指针。比如,让我们对上面的例子进行改动,利用virtual。
#include<iostream>
using namespace std;
class B
{
public:
B()
{cout<<"construct called:B\n";}
~B()
{cout<<"destructor called:B\n";}
int b;
};
class B1:virtual public B
{
public:
B1() {cout<<"constuct called:B1\n";}
~B1() {cout<<"destruct called:B1"<<endl;}
int b1;
};
class B2:virtual public B
{
public:
B2() {cout<<"constuct called:B2\n";}
~B2() {cout<<"destruct called:B2"<<endl;}
int b2;
};
class D:public B1,public B2
{
public:
D() {cout<<"constuct called:D\n";}
~D() {cout<<"destruct called:D"<<endl;}
int d;
};
void test()
{
D dd;
dd.B1::b=5;
dd.B2::b=10;
dd.b1=25;
dd.b2=111;
dd.d=149;
cout<<"dd.B1::b="<<dd.b<<"dd.B2::b"<<dd.b<<"dd.b1="<<dd.b1<<"dd.b2="<<dd.b2<<"dd.b"<<dd.d<<endl;//这里有改动
}
int main()
{
test();
}
运行后我们会发现不会出翔二义性了,对象就只有一个b数据成员了。
最后说一句,一个类体系中可以作为虚继承和非虚继承取决于对他的继承方式,于基类本身的定义无关。
|