首页 > 编程知识 正文

多重继承的二义性以及解决方法,二义性问题的产生

时间:2023-05-05 14:33:51 阅读:187059 作者:2076

一、调用不同基类同名成员时可能出现二义性

类a { public : void seta (inta ); int get (; 私有:英寸a; (; classb { public : void setb (intb ); int get (; 私有:英寸b; (; class c :公共a,公共b {公共: void SETC (intc ); int getC (; 私有:英寸; (; obj.get (; 时间有二义性。 由于c类分别从A类b类继承了两个不同版本的get ()成员函数,因此obj.get; 编译器不知道要调用哪个get ()版本。

这样的二义问题经常有两种解决方法。

(1)使用作用域标识符) :删除。

obj.A:get (;

obj.B:get (;

(2) c类中也定义了成员函数get ) )函数的话,拥有c类的客体obj为get ) )函数obj.get )的存取就没有二义性。 这是因为,如果派生类的成员与基类的成员重复,则调用派生类的同名成员。

类a { public : void seta (inta ); int get (; 私有:英寸a; (; classb { public : void setb (intb ); int get (; 私有:英寸b; (; class c :公共a,公共b {公共: void SETC (intc ); int get (; //这里这样改为private: int c; (; 二、访问公共基类成员时可能出现二义性

如果一个派生类具有多个基类,并且这些基类具有公共基类,则称为菱形继承。 此时,对该公共基类成员的访问可能是次要的。

class A{ public: void disp (; 私有:英寸a; (; classb 1: publica { public : void dispb1(; private: int b1; (; classb 2: publica { public : void dispb2(; private: int b2; (; class C:public B1,public B2{ public: void dispC (; 私有:英寸; (; 在这样结构中,在创建c类对象c1的情况下:

C c1;

以下两种访问具有二义性。

c1.disp (;

c1.A:disp (;

这是因为B1、B2分别继承了来自a类的disp )成员函数的副本,所以c类分别具有从B1、B2类的不同根继承的disp )版本。 这两个版本的函数完全相同,但语句“c1.disp”; ”调用从类B1继承的disp (是调用还是从类B2继承的disp ) ) )是二义性的原因。

语句“c1.A:disp ()”二义性产生的理由相同,但以下两个调用语句是正确的。

c1.B1:disp (;

c1.B2:disp (;

“B1:”和“B2:”的限制指定了从哪个路径继承的disp (

虽然可能需要在一个类中包含间接公共基类的多个同名成员,但可以在不同的数据成员中存储不同的数据,也可以使用构造函数单独初始化。 但是,在很多情况下,这种现象是人们不想要的。

保留多个数据成员的副本不仅占用大量存储空间,而且很难访问成员。 另外,实际上不需要拥有多个副本。 因此,c提供了虚拟基类(Virtual Base Class )技术来解决此问题。

classa{public:a(i(intI ) :a ) I ) {} int a; void disp () { cout'Member of A: a='aendl; }; classb 1: virtual publica { public : B1 (intj ) :a(j ) {} int b1; (; classb 2: virtual publica { public : B2 (intj ) :a(j ) {} int b2; (; class C:public B1,publicB2{public:c(intj ) :A(j )、B1 ) j )、B2 ) j ) {} int c; void dispc () { cout'Member of C: c='cendl; }; int main () (抄送); c.a=1; c.b1=2; c.c=3; c.disp (; 返回0; () ) ) ) )。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。