C++多继承中的二义性问题

    在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;
}

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








评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值