多重继承引发的二义性问题及解决方法分析



首先了解:

1.类的继承:派生类拥有其基类拥有的所有数据成员与成员函数,但访问属性不同。

2.类的派生:派生类可以加入新的基类不拥有的数据与函数。

 

多重继承:一个类派生出多个类,多个类派生出一个类

性质与规则:

1.声明方法:class D:public A,private B,protected C{}

2.调用顺序:先调用A的构造函数,再到B,再到C。虚基类->非虚基类->子对象->派生类。

 

问题:

1.二义性问题:派生类与基类中存在名字相同的数据或函数,使得函数无法判断与调用。

     

解决方法:

1.在引用数据成员或成员函数时指明其作用域。(类名::数据名)

2.同名覆盖(函数重载):派生类新增的同名成员将会覆盖基类中的同名成员,不论有多少个基类,而且实现的途径是利用派生类的新增成员,既要有同名的,则在直接调用不加类名作用域时就会调用派生类的成员。

3.虚基类(虚拟继承):让继承间接共同基类时只保留一份成员。

                   Class A

                   Class B:virtual public A

                   Class C:virtual public A

                   Class D:public B,public C

此时,AB的虚基类,AC的虚基类。

   A

Int data;

Void fun();


  B

Int A::data;

Void A::fun()

Int data_b;


  C

 Int A::data

Void A::fun()

 Int data_c;



   D

 Int B::data;

 Int C::data;

 Int data_b;

 Int data_c;

Void B::fun()

Void C::fun()

Int data_d;

Void fun_d();


原来BC中都有int A::data,到D中分别变成int B::dataint C:: data。但是,加了虚拟继承virtual后,BC中的int A::data就多了一个标志virtual,变成int virtual A::data,而带有virtual的成员在D中就会被合并成一个,这就是虚拟继承的本质。

至于构造函数,与普通继承派生就会有所不同。BC实际上是还是普通继承,所以构造函数写法不变。而D类中含有A的成员且不重复,其实已经可以把A看作是D的直接基类了(体现了虚基类的”虚”),所以D的构造函数就要调用A的构造函数,由A的构造函数来初始化DA的数据,而不是从BC中继承。

4.虚函数:在基类声明函数是虚拟的,不是实际存在的,在派生类中才正式定义此函数。作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数(目标是能够用同一种方式去调用同一类族中不同类的所有的同名函数)

 

问题?

类族,每个类都有一个同名的函数display()A<-B<-C<-D<-E<-F。要想调用不同派生类的同名函数,就要用多个类名或者多个指向派生类的指针如a.display().b.display().....,不方便。

 

这里的”同一种方法”是?

使用同一基类的指针或引用,调用同一类族中不同类虚函数,如用A的指针pt指向BCDEFpt->display()来调用。

 

为什么使用基类指针可以访问到派生类的成员?

基类指针指向的是基类部分这是毋庸置疑的,但是基类的同名函数声明成了virtual,而指针指向的派生类存在同名函数,所以这里有派生类的同名函数取代的基类的virtual函数变成了基类的一部分(体现虚函数的”虚”),所以使用基类指针却可以访问到派生类的成员。

 

虚函数与函数重载方法的区别?

使用的环境不同。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章