精华内容
下载资源
问答
  • 1. 什么是多重继承二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 classA{ public: voidf(); } classB{ public: voidf(); voidg(); } classC:public...

    1. 什么是多重继承的二义性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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,则c1.f();具有二义性,而c1.g();无二义性(同名覆盖)。

    2. 解决办法一 -- 类名限定

    调用时指名调用的是哪个类的函数,如

    1
    2
    c1.A::f();
    c1.B::f();

    3. 解决办法二 -- 同名覆盖

    在C中声明一个同名函数,该函数根据需要内部调用A的f或者是B的f。如

    1
    2
    3
    4
    5
    6
    7
    8
    class C:public A,public B{
    public:
        void g();
        void h();
        void f(){
            A::f();
        }
    };

     4. 解决办法三 -- 虚基类(用于有共同基类的场合)
    virtual 修饰说明基类,如:

    1
    class B1:virtual public B

    虚基类主要用来解决多继承时,可能对同一基类继承继承多次从而产生的二义性。为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。注意:需要在第一次继承时就要将共同的基类设计为虚基类。虚基类及其派生类构造函数建立对象时所指定的类称为最(远)派生类。

    • 虚基类的成员是由派生类的构造函数通过调用虚基类的构造函数进行初始化的。
    • 在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的缺省构造函数。
    • 在建立对象时,只有最派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类的构造函数的调用被忽略。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class B{
        public:
        int b;
    }
     
    class B1:virtual public B{
        priavte:
        int b1;
    }
     
    class B2:virutual public B{
        private:
        int b2;
    }
     
    class C:public B1,public B1{
        private:
        float d;
    }
     
    C obj;
    obj.b;//正确的

     如果B1和B2不采用虚继续,则编译出错,提示“request for member 'b' is ambiguous”。这是因为,不指名virtual的继承,子类将父类的成员都复制到自己的空间中,所以,C中会有两个b。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #include<iostream>
    using namespace std;
     
    class B0{
    public:
        B0(int n)    {
            nv=n;
            cout<<"i am B0,my num is"<<nv<<endl;
        }
        void fun()    {
            cout<<"Member of Bo"<<endl;
        }
    private:
        int nv;
    };
     
    class B1:virtual public B0{
    public:
        B1(int x,int y):B0(y){
           nv1=x;
           cout<<"i am  B1,my num is "<<nv1<<endl;
        }
    private:
        int nv1;
    };
     
    class B2:virtual public B0{
    public:
        B2(int x,int y):B0(y){
            nv2=x;
            cout<<"i am B2,my num is "<<nv2<<endl;
        }
    private:
        int nv2;
    };
     
    class D:public B1,public B2{
    public:
        D(int x,int y,int z,int k):B0(x),B1(y,y),B2(z,y){
           nvd=k;
           cout<<"i am D,my num is "<<nvd<<endl;
        }
    private:
        int nvd;
    };
     
    int main(){
        D d(1,2,3,4);
        d.fun();
        return 0;
    }

     d.fun()的结果是:

    1
    2
    3
    4
    5
    i am B0,my num is 1
    i am B1,my num is 2
    i am B2,my num is 3
    i am D,my num is 4
    Member of Bo

     

    转载于:https://www.cnblogs.com/liangxiaofeng/p/5678912.html

    展开全文
  • 由此c++引入了,多重继承的概念,也就是允许一个派生类指定多个基类,这样就被叫做多重继承。 如下代码: #include "stdafx.h" #include <iostream> #pragma warning(disable:4996) #include <string>...

    实际的业务场景中,一些事物会有多个属性。由此c++引入了,多重继承的概念,也就是允许一个派生类指定多个基类,这样就被叫做多重继承。

    如下代码:

    #include "stdafx.h"
    #include <iostream>
    #pragma warning(disable:4996)
    #include <string>
    
    using namespace std;
    
    class car{
    public:
    	car(){
    		cout << "this is car" << endl;
    	}
    	void print(void)
    	{
    		cout << "car class print" << endl;
    	}
    };
    
    class truck:public car
    {
    public:
    	truck(){
    		cout << "this is truck" << endl;
    	}
    	void truck_print(void){
    		cout << "truck::truck_print" << endl;
    	}
    };
    
    class bus:public car
    {
    public:
    	bus(){
    		cout << "this is bus" << endl;
    	}
    	void bus_print(void){
    		cout << "bus::bus_print" << endl;
    	}
    };
    
    class train :public truck, public bus{
    public:
    	train(){
    		cout << "this is train" << endl;
    	}
    	void train_print(void){
    		cout << "train::train_print" << endl;
    	}
    };
    
    int main(int argc, char *argv[])
    {
    	train test1;//多重继承的构造顺序和继承列表中基类的排列顺序一致,不是和它的初始化列表中的顺序
    //一致,所以先执行truck中的构造函数,truck先执行car的构造函数。再执行bus中的构造函数,bus中先执行
    //car中的构造函数
    	/*this is car
    this is truck
    this is car
    this is bus
    this is train*/
    	test1.train_print();//train::train_print
    	test1.truck_print();//truck::truck_print
    	test1.print();//出现二义性,print成员函数不明确。因为类bus和truck继承car的时候,都分别对
    //car中的成员函数print做了一份拷贝。train在继承bus和truck时对bus和truck多了拷贝。所以
    //test1.print()无法访问那个基类的print。
        car *p_car = &test1;//同样会产生二义性,将上面的继承按照下面的方法二,改为虚继承即可。
    
    	return 0;
    }

    消除二义性的方法:

    1.加上全局符指定使用哪一份拷贝。如:

    test1.truck::print();                
    test1.bus::print();

    2.使用虚继承,这样的话。派生类train只有一份基类car的拷贝了。如:

    将上面的

    class truck:public car
    class bus:public car

     改为:

    class truck:virtual public car
    class bus:virtual public car

     

    展开全文
  • 多重继承二义性以及解决方法

    千次阅读 2016-07-24 16:07:24
    //多重继承二义性以及解决方法 //学习目的:了解类的继承原理及多重继承二义性解决方法。 /* //本程序代码来源《MFC权威剖析》p68 */ ////////////////////第一种多重继承二义性//////////////// ...

    //多重继承的二义性以及解决方法
    //学习目的:了解类的继承原理及多重继承二义性的解决方法。
    /*

    //本程序代码来源《MFC权威剖析》p68
    */

    第一种多重继承的二义性
    class Employee
    {
    public:
     char Name[40];
     bool Sex;
    };
    class Worker : public Employee
    {
    };
    class Manager : public Employee
    {
    };
    class Engineer : public Worker, public Manager
    {
    };
    //Engineer的实例化对象内存中包含两个Employee子对象,分别属于Worker和Manager子对象,
    //这样在该实例的内部就封装了两套员工个人档案,显然是错误的。
    {
     Engineer eng;
     eng.Worker::Sex = true;
     eng.Manager::Sex = false;//eng的性别即使男又是女
    }
    /解决办法
    //在父类存在共同双亲的情况下,可以通过虚拟基类来解决。
    //虚拟基类的作用是:如果在一个派生类的继承结构中,存在两个同样的虚拟基类,那么
    //该类的实例化对象内存中只存在一个虚拟基类的子对象。
    //事例
    class Employee
    {
    public:
     char Name[40];
     bool Sex;
    };
    class Worker : public virtual Employee  //Employee
    {
    };
    class Manager : public virtual Employee  //Employee
    {
    };
    class Engineer : public Worker, public Manager
    {
    };
    //这样的继承方式,虚拟基类的子对象不再包含在每个父类中,而是单独存在。
    //父类对象中存在一个指向其虚拟父类子对象的一个指针,该指针被称为虚父类指针,
    //由编译器生成。这样就保证了在多重继承时,子类实例中只存在一个虚拟基类的子对象。
    //但同名的非虚拟基类的子对象没有被合并。

    /第二种多重继承的二义性
    class ParentA
    {
    public:
     void fun() {printf("%d\n", m_Value); };
    private:
     int m_Value;
    };
    class ParentB
    {
    public:
     void fun() {printf("%d\n", m_Value); };
    private:
     int m_Value;
    };
    class Son : public ParentA, public ParentB
    {
    };
    ///解决办法
    //在父类没有共同双亲的情况下,一般在子类中将名字冲突的成员重新定义,
    //以此解决二义性。

    /使用虚拟基类需要注意的问题

    [html] view plain copy
    1. #include "stdio.h"  
    2. class Base  
    3. {  
    4. public:  
    5.  Base(){printf("Base is constructed  as default\n");}  
    6.  Base(int i)   
    7.  {   
    8.   m_iValue=i;  
    9.   printf("Base is constructed  in constructing list\n");  
    10.  }  
    11.  ~Base(){printf("Base is deconstructed\n");}  
    12.    
    13.  int GetiValue()const  
    14.  {   
    15.   return m_iValue;   
    16.  }  
    17. private:  
    18.  int m_iValue;  
    19. };  
    20. class ParentA :public virtual Base  
    21. {  
    22. public:  
    23.  ParentA(){}  
    24.  ParentA(int i,float f):Base(i)  
    25.  { m_fValue=f; }  
    26.  float GetfValue()const  
    27.  {   
    28.   return m_fValue;   
    29.  }  
    30. private:  
    31.  float m_fValue;  
    32. };  
    33. class ParentB :public virtual Base  
    34. {  
    35. public:  
    36.  ParentB(){}  
    37.  ParentB(int i,char c):Base(i)  
    38.  { m_cValue=c; }  
    39.    
    40.  char GetcValue()const  
    41.  {   
    42.   return m_cValue;   
    43.  }  
    44. private:  
    45.  char m_cValue;  
    46. };  
    47. class Son:public ParentA,public ParentB  
    48. {  
    49. public:  
    50.  Son(int i,float f,char c):ParentA(i,f),ParentB(i,c)  
    51.  { }  
    52.  void Output()  
    53.  {  
    54.   printf("son member is %d  %8.2f  %c\n",  
    55.    GetiValue(),GetfValue(),GetcValue());  
    56.  }  
    57. };  
    58.   
    59. int main(int argc, char* argv[])  
    60. {  
    61.  Son son(6,92.33,'D');  
    62.  son.Output();    
    63.  return 0;  
    64. }  
    65. /*输出  
    66. Base is constructed  as default  
    67. son member is -858993460     92.33  D  
    68. ase is deconstructed  
    69. */  
    70. //由程序输出可以看出,虚拟基类只被构造一次,销毁一次,所以只存在一个子对象。  
    71. //但Base基类被调用的是默认构造函数,ParentA和ParentB对虚拟基类的构造无效。  
    72. //其实,为了保证虚拟基类只被构造一次,虚拟基类的构造函数不能按照传统的方式调用,  
    73. //即不能被直接子类调用,而是由当前最底层次类的构造函数调用,该类被称为最派生类。  
    74. //道理其实很简单,和虚函数原理是一样的。  
    75. //如果将Son的构造函数改成:  
    76. Son(int i, float f, char c):ParentA(i, f),ParentB(i, c),Base(i){}  
    77. /*则输出  
    78. Base is constructed  as default  
    79. son member is 6     92.33  D  
    80. ase is deconstructed  
    81. */  



    //应用虚拟基类虽然解决了基类子对象重复问题,但还不能完全消除二义性的可能。
    //如果两个直接父类同时定义了同名的函数,则还会产生二义性。

    展开全文
  • 多重继承二义性问题

    千次阅读 2010-12-17 15:10:00
    C++ 多重继承 二义性

     

    1、继承性二义性问题

    多个子类同时继承与同一个基类后,其派生类在访问基类成员时,会出现二义性问题,因为派生类无法选择继承路径。解决办法,通过使用虚拟继承可以解决这类二义性问题。

     

    2、非继承性二义性问题

    子类继承多个父类,并且这个多个父类具有相同命名的成员(只要名称相同,不区分函数参数或者成员类型);当子类调用父类相同命名成员时,会出现二义性问题,因为派生类不能区分调用哪个父类的成员。解决办法,通过使用指定父类名称可以解决这类二义性问题。

     

    此二类二义性问题代码示例

    继承性二义性代码示范:

    #include <iostream>

    using namespace std;

    /**//*

        继承关系说明:A是B和C的基类,B和C是D的基类

    */

    class A

    {

    public:

        int a;

    };

    class B:public A

    {

    public:

        int b;

    };

    class C:public A

    {

    public:

        int c;

    };

    class D:public B,public C

    {

    public:

        int d;

    };

    int main()

    {

        D d;

        d.a = 100;

        return 0;

    }

    编译后会出现以下编译错误:

    error C2385: ambiguous access of 'a'

    究其原因,因为AD的间接基类,通过D访问A的数据成员有两条路可走,一是D->B->A,另外一条是:D->C->A.所以导致了二义性。

    解决:

    这可以通过虚基类来解决二义性问题,如果采用虚基类方式来定义派生类,则在创建派生类对象时,类层次结构中某个虚基类的成员只出现一次。即基类的一个副本被所有的派生类对象所共享。修改代码如下后即可解决:

    #include <iostream>

    using namespace std;

    /**//*

        继承关系说明:A是B和C的基类,B和C是D的基类

    */

    class A

    {

    public:

        int a;

    };

    class B:public virtual A  //A是B的虚基类

    {

    public:

        int b;

    };

    class C:public virtual A  //A是C的虚基类

    {

    public:

        int c;

    };

    class D:public B,public C

    {

    public:

        int d;

    };

    int main()

    {

        D d;

        d.a = 100;

        return 0;

    }

     

     

    非继承二义性代码示范:

    class CBaseOne

    {

    public:

    int mydata;

     

    };

     

    class CBaseTwo

    {

    public:

    int mydata;

     

     

    class CMultiInheritance: public CBaseOne, public CBaseTwo

    {

    public:

    void OutPut(void);

     

    };

    void CMultiInheritance::OutPut()

    {

    this->mydata = 10;

    }

    编译后会出现如下错误

    error C2385: ambiguous access of 'mydata'

    究其原因是因为这两个父类同时有mydata这个数据类型,多重继承的子类在选取使用父类成员时出现二义性。

    解决:

    通过指定父类类名来调用父类成员可以解决这个问题,代码如下:

    class CBaseOne

    {

    public:

    int mydata;

     

    };

     

    class CBaseTwo

    {

    public:

    int mydata;

     

     

    class CMultiInheritance: public CBaseOne, public CBaseTwo

    {

    public:

    void OutPut(void);

     

    };

    void CMultiInheritance::OutPut()

    {

    this->CBaseOne::mydata = 10;

    }

    展开全文
  • 多重继承二义性

    2018-06-10 02:05:20
    先以一个例子来引入多重继承出现的问题:#include &lt;iostream&gt;using namespace std;class Person{ public : void sleep(){cout&lt;&lt;"this is a sleep function"&lt;&lt...
  • 多重继承造成二义性

    2017-03-20 23:13:10
    多重继承容易造成二义性(比如同时从两个类继承了函数名一样的函数,到底调用哪一个),解决方式是在调用的函数之前加上想用的类名::(d.A::hello()//调用从A类继承来的那个hello函数)。
  • 一个派生类的基类只有一个则称之为单继承。 多重继承:一个派生类有两个或多个基类,派生类从两个或多个基类中继承所需的属性。...Java 用接口解决多重继承的问题,但是不是通过多重继承这种方式做的。 声明多重
  • c/c++ 多重继承下的二义性解决方法

    千次阅读 2014-10-18 16:22:52
     主要用来解决继承时,可能对同一基类继承继承多次从而产生的二义性。  为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。  注意:需要在第一次继承时就要将共同的基类设计为虚基类 ...
  • 示例代码: #include<...//虚拟继承 class B : virtual public A { public: B() { a = 200; } }; //虚拟继承 class C : virtual public A { public: C() { a = 300; } }; class D : public B
  • //虚拟继承是为了解决多重继承而出现的,比如 /* A / \ B C \ / D 如果直接 class A{}; class B : public A{} class C : public A{} class D : public B, public C{} 那么在创建D的对象时候,将会生成2...
  •  ...多重继承:一个类派生出多个类,多个类派生出一个类 性质与规则: 1.声明方法:class D:public A,private B,protected C{} 2.调用顺序:先调用A的构造函数,再到B,再到C。虚基类->非虚基
  • 转自:... 1. 什么是多重继承二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cla
  • 下面程序代码,在执行时,会产生二义性错误,分析为什么会产生二义性,如何修改程序来解决二义性问题?#include #include using namespace std; class Base { protected: int a; public: Base( ) { a=5;} void ...
  • C++多重继承经常出现,下面我们来讨论一种比较特殊的多重继承方式--菱形继承。 问题的提出:我们定义了一个动物类A,由A又可以派生出水栖生活动物类B(鲨鱼、螃蟹等)和陆栖生活动物类C(狮子、老虎等),那么...
  • 转自:... 1. 什么是多重继承二义性 class A{ public: void f(); } class B{ public: void f(); void g(); } class C:public A,publi...
  • C++多重继承二义性避免

    千次阅读 2016-05-14 17:34:24
    1. 什么是多重继承二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A{ public:  void f(); }   class B{ public:  void f();  void g(); }   ...
  • 多重继承的弊端 解决方案一: 使用"类名"::进行指定, 指定调用从哪个基类继承的方法!!! wsc.Father::dance(); wsc.Mother::dance(); 解决方案: 在子类中重新实现这个同名方法, 并在这个方法内部, 使用基类名进行...
  • 多重继承中二义性的消除

    千次阅读 2014-08-16 18:11:42
    类A派生B和C, 类D从B,C派生,如何将...这道题实际上考查的是如何消除多重继承引起的向上继承二义性问题。程序代码如下所示: class A {}; class B : public A {}; class C : public A {}; class D : public
  • 一、派生类构造函数的写法(1)冒号...(2)需要注意的是:冒号后面是对基类构造函数的调用,而不是声明,所以括号里的参数是实参、基类构造函数调用规则(1)通过派生类创建对象时必须要调用基类的构造函数,这是
  • 多重继承: 例1:两个父类中的同名函数如何区分示例 解决方法:在子类对象调用print( )函数时加上某个父类的作用域符号 附上例代码: //小问学编程 #include<iostream> using namespace std; class A //父类...
  • 主要包括类的声明、对象定义、构造函数和析构函数、运算符重载、继承和派生、多态实现等。 课程需要有C语言程序设计的基础(可以利用本人开出的《C语言与程序设计》系列课学习)。学习者能够通过...
  • 主要包括类的声明、对象定义、构造函数和析构函数、运算符重载、继承和派生、多态实现等。 课程需要有C语言程序设计的基础(可以利用本人开出的《C语言与程序设计》系列课学习)。学习者能够通过...
  • 解决派生类多重继承产生的二义性

    千次阅读 2013-05-21 13:44:58
    //多重继承解决访问歧义的方法 // 基类名::数据成员(数据函数(参数列表)) //1、明确指定是访问那个基类的成员 // 当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此基类中的成员时,将...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,816
精华内容 3,126
关键字:

多重继承二义性的解决方法