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

C++多重继承二义性解决的更多相关文章

  1. C++学习之路—继承与派生(三):多重继承与虚基类

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 多重继承是指一个派生类有两个或多个基类.例如,有 ...

  2. C++学习之虚继承

    http://blog.csdn.net/wangxingbao4227/article/details/6772579 C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同 ...

  3. 虚拟继承C++

    C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类.这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数 ...

  4. C++虚继承的概念[转]

    C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类.这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数 ...

  5. C/C++面试题总结(1)

    首先说一下,这些东西,有的是必须掌握的,有的是面试时你讲出来就是闪光点.自己把握.把握不好的都搞懂.实在不行背下来. 由于时间关系,总结的比较随意,有的就直接贴链接了,希望理解一下. 第一篇:基础(必 ...

  6. C++虚继承的概念(转)

    http://blog.csdn.net/wangxingbao4227/article/details/6772579 C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同 ...

  7. C++虚继承作用

    C++虚继承可以防止多重继承产生的二义性问题. 虚继承,就是在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,如下面代码中的base类.虚继承在多重继承的时可以防止二义性. clas ...

  8. C++笔记(仅C++特性,需C语言基础)

    C++复习笔记一(类的声明定义应用与构造函数析构函数部分)const在C语言中是"不能被改变值的变量",而在C++种子则是"一种有类型描述的常量",常量必须初始 ...

  9. c/c++: c++继承 内存分布 虚表 虚指针 (转)

    http://www.cnblogs.com/DylanWind/archive/2009/01/12/1373919.html 前部分原创,转载请注明出处,谢谢! class Base  {  pu ...

随机推荐

  1. bzoj 1015 星球大战starwar

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1015 题解: 如果按照题目的意思,每次删点.删边太困难了……于是采用逆向思维,构造出最后的 ...

  2. c json实战引擎五 , 优化重构

    引言 scjson是一个小巧的纯c跨平台小巧引擎. 适用于替换老的cJSON引擎的场景. 数据结构和代码布局做了大量改进.优势体现在以下几个方面: 1) 跨平台 (window 10 + VS2017 ...

  3. udp调用connect有什么作用(转)

    原文链接如下: http://blog.csdn.net/wannew/article/details/18218619 整理一下.1:UDP中可以使用connect系统调用 2:UDP中connec ...

  4. leetcode 之Valid Palindrome(26)

    现在开始进入字符串系列. 判断回文串的.首尾各定义一个指针,然后相比较.难点在于如何提出非字母数字的字符. bool isValidPalind(string s) { //转为小写,注意这个函数的用 ...

  5. SRM 563 Div1 500 SpellCards

    Description 有n张符卡排成一个队列,每张符卡有两个属性,等级lili和伤害didi. 你可以做任意次操作,每次操作为以下二者之一: 把队首的符卡移动到队尾. 使用队首的符卡,对敌人造成di ...

  6. 字符串aaaa......bbbb....ccc...dddddd用正则替换为abcd

    public static void main(String[] args) { String s = "aaaa......bbbb....ccc...dddddd"; Stri ...

  7. http-server:一个简单的零配置命令行的http服务器

    首先简介一下http-server: http-server是一个简单的零配置命令行http服务器,他对于生产使用来说足够强大,他是简单和可删节足以用于测试,足够简单易用,而且可用于本地开发 1.首先 ...

  8. poj 3404&&poj1700(贪心)

    Bridge over a rough river Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4143   Accept ...

  9. .NET 二进制序列化器,SOAP序列化器,XML序列化器

    这里就不说JSON序列化了,只介绍三种:二进制序列化器,SOAP序列化器,XML序列化器 直接上代码: /// <summary> /// 二进制序列化器. /// 最节省流量,压缩程度最 ...

  10. 归并排序(MergeSort)

    原帖:http://blog.csdn.net/magicharvey/article/details/10192933 算法描述 归并排序(MergeSort)是采用分治法的一个非常典型的应用.通过 ...