精华内容
下载资源
问答
  • 请描述多继承中出现的二义性问题及解决措施
    千次阅读
    2018-10-08 09:45:22

    转自:https://www.cnblogs.com/tenjl-exv/p/7625484.html

    多继承的二义性主要分为两种:

    1. 调用不同基类的同名成员时可能出现二义性
    2. 访问共同基类的成员可能出现二义性

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

    class A
    {
        public:
            void setA(int a);
            int get();
        private:
            int a;
    } ;
    class B
    {
        public:
            void setB(int b);
            int get();
        private:
            int b;
    } ;
    
    class C:public A,public B
    {
        public:
            void setC(int c);
            int getC();
        private:
            int c;
    };

     在执行obj.get();时将是有二义性的。因为类C分别从类A类B继承了两个不同版本的get()成员函数,因此,obj.get();到底调用哪个get()版本,编译器将无从知晓。

    有两种解决方法:

    (1)使用作用域分辨符::加以消除。

    obj.A::get();

    obj.B::get();

    (2)在类C中也定义成员函数get()函数,则有类C的对象obj访问get()函数obj.get()没有二义性,这是因为当派生类中的成员与基类中的成员重名时,派生类中的同名成员将被调用。

    class A
    {
        public:
            void setA(int a);
            int get();
        private:
            int a;
    } ;
    class B
    {
        public:
            void setB(int b);
            int get();
        private:
            int b;
    } ;
    
    class C:public A,public B
    {
        public:
            void setC(int c);
            int get();
                    //此处改为这样    
        private:
            int c;
    };

     2、访问共同基类的成员可能出现二义性

    菱形继承问题

    class A
    {
        public:
            void disp(); 
        private:
            int a;
    };
    
    class B1:public A
    {
        public:
            void dispB1();
        private: 
            int b1;
    };
    class B2:public A
    {
        public:
            void dispB2();
        private: 
            int b2;
    };
    
    class C:public B1,public B2
    {
        public:
            void dispC();
        private: 
            int c;
    };

     

    在此类结构下,如果创建类C的对象c1:

    C c1;

    则下面的两个访问都有二义性:

    c1.disp();

    c1.A::disp();

    不过下面的两条调用语句却是正确的:

    c1.B1::disp();

    c1.B2::disp();

    解决方法:

    采用虚基类的方式,代码如下:

    class A
    {
        public:
            void disp(); 
        private:
            int a;
    };
    
    class B1:virtual public A
    {
        public:
            void dispB1();
        private: 
            int b1;
    };
    class B2:virtual public A
    {
        public:
            void dispB2();
        private: 
            int b2;
    };
    
    class C:public B1,public B2
    {
        public:
            void dispC();
        private: 
            int c;
    };

     

    更多相关内容
  • C++多继承中二义性问题

    千次阅读 多人点赞 2018-05-24 17:35:46
    在C++,派生类继承基类,对基类成员的访问应该是确定的、唯一的,但是常常会有以下情况导致访问不一致,产生二义性。 1.在继承时,基类之间、或基类与派生类之间发生成员同名时,将出现对成员访问的不确定性——...
        在C++中,派生类继承基类,对基类成员的访问应该是确定的、唯一的,但是常常会有以下情况导致访问不一致,产生二义性。
        1.在继承时,基类之间、或基类与派生类之间发生成员同名时,将出现对成员访问的不确定性——同名二义性。
        2.当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生另一种不确定性——路径二义性。

        1.

                                                                        

    “倒三角”问题——同名二义性

    #include "iostream"
    
    using namespace std;
    
    class Parent_f
    {
    public:
        void show()
        {
            cout<<"This is Parent_f\n";
        }
    };
    class Parent_m
    {
    public:
        void show()
        {
            cout<<"This is Parent_m\n";
        }
    };
    class Son:public Parent_f,public Parent_m
    {
    public:
        void display()
        {
            cout<<"This is son\n";
        }
    };
    int main()
    {
        Son son;
        son.show();
        son.display();
        cout << "Hello world!" << endl;
        return 0;
    }

    上面的代码中,2个父类派生一个子类,但两个父类中都有同名的成员函数。派生出的子类产生二义性问题,编译时会报:

    error: request for member 'show' is ambiguous

        解决方法:

        (1)利用作用域限定符(::),用来限定子类调用的是哪个父类的show()函数

    son.Parent_f::show();
        (2)在类中定义同名成员,覆盖掉父类中的相关成员
    class Son:public Parent_f,public Parent_m
    {
    public:
        void display()
        {
            cout<<"This is son\n";
        }
    
        void show()
        {
            cout<<"show:This is son.\n";
        }
    };


    2.

                                                        

    “菱形”问题——路径二义性

        有最基类A,有A的派生类B、C,又有D同时继承B、C,那么若A中有成员a,那么在派生类B,C中就存在a,又D继承了B,C,那么D中便同时存在B继承A的a和C继承A的a,那么当D的实例调用a的时候就不知道该调用B的a还是C的a,就导致了二义性。

    #include "iostream"
    
    using namespace std;
    
    class Grandpa
    {
    public:
        int year_old;
    };
    
    class Parent_f:public Grandpa {};
    class Parent_m:public Grandpa {};
    
    class Son:public Parent_f,public Parent_m {};
    
    int main()
    {
        Son son;
        son.year_old = 10;
        cout << "Hello world!" << endl;
        return 0;
    }
    

        Grandpa为Parent_f和Parent_m的基类,而Son又继承Parent_f和Parent_m,当Son访问Grandpa的year_old时,会出现二义性错误.

        解决方法:

        (1)使用作用域限定符,指明访问的是哪一个基类的成员。

                注意:不能是Grandpa作用域下限定,因为Son直接基类的基类才是Grandpa,纵使指明了访问Grandpa的成员的话,对于Son来说,还是模糊的,还是具有二义性。

        (2)在类中定义同名成员,覆盖掉父类中的相关成员。

        (3)虚继承、使用虚基类

            教科书上面对C++虚基类的描述玄而又玄,名曰“共享继承”,名曰“各派生类的对象共享基类的的一个拷贝”,其实说白了就是解决多重多级继承造成的二义性问题。父类对祖父类的继承方式改为虚继承,那么子类访问自己从祖父类那里继承过来的成员就不会有二义性问题了,也就是将子类对象里的祖父类对象统一为一个,继承的只有一个祖父类对象,代码如下。

    #include "iostream"
    
    using namespace std;
    
    class Grandpa
    {
    public:
        int year_old;
        void show()
        {
            cout << "year_old:" << year_old <<endl;
        }
    };
    
    class Parent_f:virtual public Grandpa {};
    class Parent_m:virtual public Grandpa {};
    
    class Son:public Parent_f,public Parent_m {};
    
    int main()
    {
        Grandpa grp;
        Parent_f pa_f;
        Parent_m pa_m;
        Son son;
    
        grp.year_old = 100;
        pa_f.year_old = 55;
        pa_m.year_old = 50;
        son.year_old = 10;
    
        grp.show();
        pa_f.show();
        pa_m.show();
        son.show();
        cout << "Hello world!" << endl;
        return 0;
    }

        使用了虚基类的方法,是不是感觉简单方便多了呢








    展开全文
  • ----问题描述:卤煮之所以称之为“倒三角问题”,是因为这一类二义性问题所处的继承体系类似于倒三角形状,如图:这样,在子类就存在父类A、B的两份show(),在调用的时候就会出现二义性问题,这种问题该怎么解决呢...

    --------------------------------一、“倒三角”二义性问题-------------------------------

    问题描述:卤煮之所以称之为“倒三角问题”,是因为这一类二义性问题所处的继承体系类似于倒三角形状,如图:

    26850048edf669033ebcf00009b06eaa.png

    这样,在子类中就存在父类A、B的两份show(),在调用的时候就会出现二义性问题,这种问题该怎么解决呢?

    面对问题:

    //下面这种情况出现的二义性怎么解决?

    /*

    class grandpa

    {

    public:

    void show()

    {

    cout<

    }

    };

    class father

    {

    public:

    void show()

    {

    cout<

    }

    };

    class son:virtual public grandpa,virtual public father

    {

    public:

    void display()

    {

    cout<

    }

    };

    int main()

    {

    son son;

    son.show();

    son.display();

    cout << "Hello world!" << endl;

    return 0;

    }

    //这里的“倒三角”问题二义性怎么解决?即有两个基类共同派生出一个子类,这两个基类中又同时存在相同的功能的时候

    //派生出的子类在调用该功能的时候也会出现二义性问题  这时候该怎么解决?

    //解决方法:利用区域限定符(::)  详细解决方案见实验tempt

    */

    解决方法:区域限定符(::)

    #include

    using namespace std;

    //下面这种情况出现的二义性怎么解决?

    class grandpa

    {

    public:

    void show()

    {

    cout<

    }

    };

    class father

    {

    public:

    void show()

    {

    cout<

    }

    };

    class son:virtual public grandpa,virtual public father

    {

    public:

    void display()

    {

    cout<

    }

    };

    int main()

    {

    son son;

    son.father::show();//“倒三角”问题出现的二义性利用区域限定符(::)来解决

    son.grandpa::show();

    son.display();

    return 0;

    }

    -------------------------------------------二、“恐怖菱形”二义性问题---------------------------------------

    面对问题:

    描述:有最基类A,有A的派生类B、C,又有D同时继承B、C,那么若A中有对象a,那么在派生类B,C中就存在a,又D继承了B,C,那么D中便同时存在B继承A的a和C继承A的a,那么当D的实例调用a的时候就不知道该调用B的a还是C的a,就导致了二义性。

    图示:

    da4b260b7954380870c557968d1ccd9c.png

    解决方案:  虚基类、虚继承

    教科书上面对C++虚基类的描述玄而又玄,名曰“共享继承”,名曰“各派生类的对象共享基类的的一个拷贝”,其实说白了就是解决多重多级继承造成的二义性问题。例如有基类B,从B派生出C和D,然后类F又同时继承了C和D,现在类F的一个对象里面包含了两个基类B的对象,如果F访问自己的从基类B那里继承过来的的数据成员或者函数成员那么编译器就不知道你指的到底是从C那里继承过来的B对象呢还是从D那里继承过来的B对象。

    于是虚基类诞生了,将C和D的继承方式改为虚继承,那么F访问自己从B那里继承过来的成员就不会有二义性问题了,也就是将F对象里的B对象统一为一个,只有一个基类B对象,下面是一段代码说明了对虚基类的使用。

    #include

    using namespace std;

    class A

    {

    public:

    int i;

    void showa(){cout<

    };

    class B:virtual public A      //此处采用虚继承

    {

    public:

    int j;

    };

    class C:virtual public A      //此处采用虚继承

    {

    public:

    int k;

    };

    class D:public B,public C

    {

    public:

    int m;

    };

    int main()

    {

    A a;

    B b;

    C c;

    a.i=1;

    a.showa();

    b.i=2;

    b.showa();

    c.i=3;

    c.showa();

    D d;

    d.i=4;

    d.showa();

    //cout << "Hello world!" << endl;

    return 0;

    }

    从这个代码我们可以看出B,C,D从A那里继承过来了i这个变量并且它们之间不会有任何影响,如果B和C不是虚继承方式的,那么d.i=4;就不能编译通过了。

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

    千次阅读 2019-03-15 09:42:33
    一、调用不同基类的同名成员时可能出现二义性 class A { public: void setA(int a); int get(); private: int a; } ; class B { public: void setB(int b); int get(); private:...

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

    class A
    {
        public:
            void setA(int a);
            int get();
        private:
            int a;
    } ;
    class B
    {
        public:
            void setB(int b);
            int get();
        private:
            int b;
    } ;
    
    class C:public A,public B
    {
        public:
            void setC(int c);
            int getC();
        private:
            int c;
    };
    

    在执行obj.get();时将是有二义性的。因为类C分别从类A类B继承了两个不同版本的get()成员函数,因此,obj.get();到底调用哪个get()版本,编译器将无从知晓。

    对于这种二义性问题,常见有两种解决方法:

    (1)使用作用域分辨符::加以消除。

    obj.A::get();

    obj.B::get();

    (2)在类C中也定义成员函数get()函数,则有类C的对象obj访问get()函数obj.get()没有二义性,这是因为当派生类中的成员与基类中的成员重名时,派生类中的同名成员将被调用。

    class A
    {
        public:
            void setA(int a);
            int get();
        private:
            int a;
    } ;
    class B
    {
        public:
            void setB(int b);
            int get();
        private:
            int b;
    } ;
    
    class C:public A,public B
    {
        public:
            void setC(int c);
            int get();
                    //此处改为这样    
        private:
            int c;
    };
    

    二、访问共同基类的成员时可能出现二义性
    当一个派生类有多个基类,而这些基类又有一个共同的基类时,也就是所谓的菱形继承。这时对这个共同基类中成员的访问可能出现二义性。

    class A
    {
        public:
            void disp(); 
        private:
            int a;
    };
    
    class B1:public A
    {
        public:
            void dispB1();
        private: 
            int b1;
    };
    class B2:public A
    {
        public:
            void dispB2();
        private: 
            int b2;
    };
    
    class C:public B1,public B2
    {
        public:
            void dispC();
        private: 
            int c;
    };
    

    在此类结构下,如果创建类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)技术来解决这个问题。

    
    class A
    {
        public:
            A(int i):a(i){}
            int a;
            void disp()
            {
                cout<<"Member of A: a= "<<a<<endl;
            }
    };
    
    class B1:virtual public A
    {
        public:
            B1(int j):A(j){}
            int b1;
    };
    class B2:virtual public A
    {
        public:
                B2(int j):A(j){}
            int b2;
    };
    
    class C:public B1,public B2
    {
        public:
                C(int j):A(j),B1(j),B2(j){}
            int c;
            void dispc()
            {
                cout<<"Member of C: c= "<<c<<endl;
            }
    };
    
    int main()
    {
        C c(3);
        c.a=1;
        c.b1=2;
        c.c=3;
        c.disp();
        
        return 0;
    }
    
    展开全文
  • 菱形继承我们都知道,C++有单继承多继承两种继承方式: 单继承:如果一个类只有一个直接基类(也就是父类),我们称这种继承方式为单继承多继承:如果一个类有个父类(2个及其两个以上),我们称这种继承...
  • 继承二义性 动态关联

    2018-07-02 22:18:03
    1.关于多重继承二义性描述中,( C )是错误的。 A.一个派生类的两个基类中都有某个同名成员,在派生类对这个成员的访问可能出现二义性 B.解决二义性最常用的方法是对成员名的限定 C.基类和派生类中出现同名...
  • 问题描述 ...这样一个子类继承多个父类的问题多继承问题,如果父类之间有同名的方法或者属性,就会产生二义性继承多份父类的属性,超成资源的浪费 同名属性,产生二义性 #include "iostr...
  • 二义性

    千次阅读 2018-08-10 11:29:44
    自然语言的二义性什么意思 面这个问题.很清楚的说明了自然语言的二义性.. 用红墨水写一个“蓝”字,请问,这个字是红字还是蓝字? 可能很少有人意识到,像红字和蓝字这样...C++常见的两种二义性问题及其解决方式 ...
  • 最近被问到一个关于多继承虚函数表的问题,当时回答是可能存在个虚函数表,应该是顺序排列的,但具体怎么排列还是有些疑惑的,回答的时候到有点儿心虚。之后查了资料,做了简单的实验,可以确定的是对于继承个...
  • 缺点:如果派生类所继承个父类有相同的父类(也就是一个菱形继承结构),而派生类对象需要调用这个祖先类的方法,就会容易出现二义性。 1、java 与 C++ 的不同点在于多继承。 Java:不能多继承,只能单继承...
  • 本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三一、小鱼)... 例1:定义基类CBase,并定义CBase的派生类CDerived1和CDerived2,在定义CDerived1和CDerived2的派生类CDerived12,观察二义性。 代码
  • 上节课的内容,LR(0)存在冲突。这节课首先提出SLR进行解决。SLR的改进很简单,但还存在冲突。因此又引出LR(1)。 但是,LR(1)的状态过多,于是引出LALR化简、合并其状态。...最后,介绍了二义性与错误处理。
  • 比如qss的ANSI编码、嵌套窗口主窗口无法接收鼠标移动事件等,又比如我用qss设置窗口样式,但是项目每次重新构建以后,样式表就会不生效等问题,也花了自己不少时间去解决,所以在这里转发大神的经验,留作以后参考...
  • C++章节测验四

    2022-05-16 13:04:50
    要点检验已完成 ...关于公有继承中,关派生类对象和基类对象的关系,下列叙述不正确是() A、 派生类对象可以赋给基类对象 B、 派生类对象可以初始化基类的引用 C、 派生类对象.
  • C++中继承及virtual小结

    千次阅读 2018-04-04 18:01:17
    一、继承基础知识C++继承1.1继承的基本概念类与类之间的关系has-A,包含关系,用以描述一个类由个“部件类”构成,实现has-A关系用类的成员属性表示,即一个类的成员属性是另一个已经定义好的类。use-A,一个...
  • 多继承的概念和优缺点

    千次阅读 2013-11-03 22:20:30
    实际生活,一些事物往往会拥有两个或两个以上事物的属性,为了解决这个问题,C++引入了多重继承的概念,C++允许为一个派生类指定个基类,这样的继承结构被称做多重继承。举个例子: 人(Person)可以派生出作者...
  • C++之继承最详讲

    千次阅读 2022-05-02 18:13:24
    3.4、class关键字没有给出继承方式默认的继承方式是私有的继承方式 3.5、struct关键字没有给出继承方式默认的继承方式是公共的继承方式 3.6、那么我们可以就此总结一下class和struct的区别 3.7、关于继承方式...
  • 继承和多态

    千次阅读 多人点赞 2022-04-15 10:18:39
    目录 一、继承的概念和定义 、基类和派生类对象赋值转换 ​​​​​​​一、继承的概念和定义 继承概念:继承是类设计层次的复用 ...派生类有基类继承的成员类型(是公有是保护还是私有) ..
  • 1.(单选题)【继承与派生概念】下列关于继承描述中,错误的是( )。 A. 继承是重用的重要机制 B. C++语言不支持多重继承 C. 继承关系不是可逆的 D. 继承是面向对象程序设计语言的重要特性 正确答案:B 2.(单选...
  • 抽象类 抽象属性 接口 委托 抽象方法方法 匿名方法内容查看总目录【Unity】Unity学习笔记目录整理
  • 继承的详细介绍与理解,看了就懂

    千次阅读 2022-03-08 10:18:50
    继承的介绍继承的概念定义定义格式继承基类成员访问方式的变化基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承与友元 继承的概念定义 继承也是面向对象的三大特性之一,是为了代码能够复用的...
  • 析构也一样3、为什么派生类的构造(析构)必须调用基类的某个构造(析构)4、其他几个细节5、派生类做的三件事、派生类和基类的同名成员问题1、派生类再实现一个基类方法会怎样2、派生类如何访问被隐藏的...
  • C++---继承

    千次阅读 多人点赞 2021-04-28 21:13:18
    封装:将事务的属性和行为抽象成具体的数据和方法,使用类对数据和方法进行封装,通过权限访问限定符进行限定,使用者无序关注具体实现(隐藏),只需通过对象调用类接口。以类为单位进行管理,提高了代码的复用...
  • 多重继承(MI)

    千次阅读 2021-12-06 19:12:22
    而在多重继承中,每个直接祖先都有一个 Show()函数,这使得上述调用是二义性的。 警告:多重继承可能导致函数调用的二义性。例如,BadDude类可能从Gunslinger类和 PokerPlayer类那里继承两个完全不同的Draw()方法。 ...
  • 多重继承与菱形缺陷

    2019-01-07 17:05:58
    继承基类时,在派生类就获得了基类所有的数据成员副本。假如类B从A1和A2两个类多重继承而来,这样B类就包含A1、A2类的数据成员副本。 考虑如果A1、A2都从某基类派生,该基类称为Base,现在继承关系如下: ...
  • 文章目录高级语宫及其语法描述(一)程序语言的定义()高级语言的一般特性1、高级语言的分类2、数据类型与操作 高级语宫及其语法描述 (一)程序语言的定义 编译程序要对程序进行正确的翻译,首先要对程序设计...
  • C++学习之第十天-继承

    2021-11-07 22:43:03
    一、选择题 下面叙述错误的是(A) A.基类的protected成员在派生类仍然是protected B.基类的protected成员在public派生类...(继承方式 与 基类权限 )取交集 = 派生类权限 2、下列对派生类的描述中
  • PCL3D点云特征描述与提取(一)

    千次阅读 2021-10-08 16:45:18
    PCL3D点云特征描述与提取1 特征描述与提取的概念相关算法1.1 3D形状内容描述子1.2 旋转图像(Spin Images)1.3 PCL特征描述与提取模块类2 点云特征描述与提取入门级实例解析2.1 PCL中描述三维特征相关基础...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,722
精华内容 7,888
热门标签
关键字:

请描述多继承中出现的二义性问题及解决措施