int getb3()
{
return b3;
}
private:
int b3;
};
class A : public B2, public B1
{
public:
A(int i, int j, int k, int l):B1(i), B2(j), bb(k)
{
a = l;
cout<<"构造函数 A."<<a<<endl;
}
void print()
{
B1::print();
B2::print();
cout<<"A.print()"<<a<<","<<bb.getb3()<<endl;
}
private:
int a;
B3 bb;
};
void main()
{
A aa(1, 2, 3, 4);
aa.print();
}
该程序的输出结果为:
构造函数 B2.2
构造函数 B1.1
构造函数 B3.3
构造函数 A.4
B1.print().1
B2.print()2
A.print()4, 3
在该程序中,作用域运算符::用于解决作用域冲突的问题。在派生类A中的print()函数的定义中,使用了B1::print;和B2::print();语句分别指明调用哪一个类中的print()函数,这种用法应该学会。
二义性问题
一般说来,在派生类中对基类成员的访问应该是唯一的,但是,由于多继承情况下,可能造成对基类中某成员的访问出现了不唯一的情况,则称为对基类成员访问的二义性问题。
实际上,在上例已经出现过这一问题,回忆一下上例中,派生类A的两基类B1和B2中都有一个成员函数print()。如果在派生类中访问 print()函数,到底是哪一个基类的呢?于是出现了二义性。但是在上例中解决了这个问题,其办法是通过作用域运算符::进行了限定。如果不加以限定,则会出现二义性问题。
下面再举一个简单的例子,对二义性问题进行深入讨论。例如:
class A
{
public:
void f();
};
class B
{
public:
void f();
void g();
};
class C : public A, public B
{
public:
void g();
void h();
};
如果定义一个类C的对象c1:
C c1;
则对函数f()的访问
c1.f();
便具有二义性:是访问类A中的f(),还是访问类B中的f()呢?
解决的方法可用前面用过的成员名限定法来消除二义性,例如:
c1.A::f();
或者
c1.B::f();
但是,最好的解决办法是在类C中定义一个同名成员f(),类C中的f()再根据需要来决定调用A::f(),还是B::f(),还是两者皆有,这样,c1.f()将调用C::f()。
责任编辑:cyth