精华内容
下载资源
问答
  • 主要介绍了C++多重继承二义性原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 多重继承二义性

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

    先以一个例子来引入多重继承出现的问题:

    #include <iostream>

    using namespace std;
    class Person
    {
      public :
       void sleep(){cout<<"this is a sleep function"<<endl;}
       void eat(){cout<<"this is a eat function"<<endl;}
    };
    class Author:public Person
    {
      public:
       void writeBook(){cout<<"this is a writeBook function"<<endl;}
    };
    class Coder:public Person
    {
      public:
       void writecode(){cout<<"this is a writecode function"<<endl;}
    };
    class Teacher:public Author,public Coder
    {
       
    };
    int main()
    {
        Teacher t;
        t.writeBook();
        t.writecode();
        t.sleep();
        t.eat();
        return 0;

    }

    这是编译结果:


    这里就充分体现了多重继承的缺点,如果派生类所继承的多个基类有相同的基类,而派生类对象需要调用这个祖先类的接口方法,就会容易出现二义性。通常有两种解决方案

    1.加上全局符确定调用哪一份拷贝,上述的程序可改为:

        t.Author::sleep();
        t.Author::eat();

    2.采用虚拟继承

    class Author:virtual public Person

    class Coder:virtual public Person

    3.虚基类的构造函数和初始化

    #include <iostream>
    using namespace std;


    class base 
    {
    protected:
      int x;
        public :
           base(int x1){
              x=x1;
              cout<<"base constructor x="<<x<<endl;
           }
    };
    class base1:virtual public base
    {


        int y;
        public :
           base1(int x1,int y1):base(x1){
              y=y1;
              cout<<"base constructor y="<<y<<endl;
           }
    };
    class base2:virtual public base
    {


        int z;
        public :
           base2(int x1,int y1):base(x1){
              z=y1;
              cout<<"base constructor z="<<z<<endl;
           }
    };
    class user:public base1,public base2
    {
       int m;
       public:
       user(int x1,int y1,int z1,int m1):base(x1),base1(x1,y1),base2(x1,z1){
         m=m1;
         cout<<"base constructor m="<<m<<endl;
       }
    };
    int main()
    {
        user t(1,2,3,4);
        return 0;
    }

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

    千次阅读 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;

    }

    展开全文
  • 由此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

     

    展开全文
  • 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

    展开全文
  • 示例代码: #include<...//虚拟继承 class B : virtual public A { public: B() { a = 200; } }; //虚拟继承 class C : virtual public A { public: C() { a = 300; } }; class D : public B
  • C++primer620页说道:即使两个继承的函数具有不同的形参表也会产生错误...名字查找总是以两个步骤发生。但是多重继承得到的名字相同而形参列表不同的函数为什么锁雾不能认为是重载呢?它和重载之间有什么区别?
  • 下面程序代码,在执行时,会产生二义性错误,分析为什么会产生二义性,如何修改程序来解决二义性问题?#include #include using namespace std; class Base { protected: int a; public: Base( ) { a=5;} void ...
  • 多重继承造成二义性

    2017-03-20 23:13:10
    多重继承容易造成二义性(比如同时从两个类继承了函数名一样的函数,到底调用哪一个),解决方式是在调用的函数之前加上想用的类名::(d.A::hello()//调用从A类继承来的那个hello函数)。
  • 多重继承二义性以及解决方法

    千次阅读 2016-07-24 16:07:24
    //多重继承二义性以及解决方法 //学习目的:了解类的继承原理及多重继承二义性的解决方法。 /* //本程序代码来源《MFC权威剖析》p68 */ ////////////////////第一种多重继承二义性//////////////// ...
  • 可参考:派生类构造函数和多重继承二义性问题
  • 一个派生类的基类只有一个则称之为单继承。 多重继承:一个派生类有两...对于多重继承,c++和python等支持多重继承,但是Java是不支持的。Java 用接口解决多重继承的问题,但是不是通过多重继承这种方式做的。 声明多重
  • 菱形继承的定义如下,从Base出发,至AB汇合,因此成为菱形继承。 class Base; class SubA : public Base; class SubB : public Base; class AB : ... 1.二义性 , 如果 Base定义了一个函数 fun, 在
  • 多重继承中二义性的消除

    千次阅读 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
  • 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(); }   ...
  • 二义性问题 1.多重继承派生类 除去一个类从一个基类派生, C++还支持一个派生类同时继承多个基类。 这样理解:子女既可以继承父亲的特点,也可以继承母亲的特点 多重继承派生类的定义 如果已经定义了多个基类, ...
  • 多重继承转换二义性

    2011-01-08 22:01:00
    如果一个类继承多个基类,而且这些基础继承相同的基类,则进行类型转换时,如果转换成相同的父类型,编译时会产生二义性错误:  class A  {  virtual void test(){} ;  } ;  ...
  • 转自:... 1. 什么是多重继承二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cla
  • 继承二义性 动态关联

    2018-07-02 22:18:03
    1.关于多重继承二义性的描述中,( C )是错误的。 A.一个派生类的两个基类中都有某个同名成员,在派生类中对这个成员的访问可能出现二义性 B.解决二义性最常用的方法是对成员名的限定 C.基类和派生类中出现同名...
  • 一、派生类构造函数的写法(1)冒号...(2)需要注意的是:冒号后面是对基类构造函数的调用,而不是声明,所以括号里的参数是实参、基类构造函数调用规则(1)通过派生类创建对象时必须要调用基类的构造函数,这是
  • Q1:关于类作用域与名字二义性• 在多重继承下,名字查找同时在所有基类子树上并行进行• 成员函数或数据成员的查找通过两步实现:1) 名字查找2) 确定查到的名字是否合法 • 在名字查找阶段并不考虑成员的访问级别•...
  • C++多重继承经常出现,下面我们来讨论一种比较特殊的多重继承方式--菱形继承。 问题的提出:我们定义了一个动物类A,由A又可以派生出水栖生活动物类B(鲨鱼、螃蟹等)和陆栖生活动物类C(狮子、老虎等),那么...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,476
精华内容 4,190
关键字:

多重继承二义性