关于C++多重继承的问题
Question about multi-inheritance in C++?
我有以下代码:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
#define MNAME 30
class Person {
public:
char name[MNAME + 1];
};
class Student : public Person {
};
class Staff : public Person {
};
class Faculty : public Student, public Staff {
};
int _tmain(int argc, _TCHAR* argv[])
{
Faculty faculty;
cout << "Address of faculty.Person::name: " << &faculty.Person::name << endl;
cout << "Address of faculty.Student::name: " << &faculty.Student::name << endl;
cout << "Address of faculty.Staff::name: " << &faculty.Staff::name << endl;
getch();
return 0;
}
执行时,程序给出结果:
Address of faculty.Person::name: 0012FF20 // **Line 1**
Address of faculty.Student::name: 0012FF20 // **Line 2**
Address of faculty.Staff::name: 0012FF3F // **Line 3**
我不明白。为什么Line 1
和Line 2
中的地址与Line 3
不同,而学生和教职员工都从人那里继承姓名?
当你以这种方式进行多重继承时,你会得到祖父类的两个副本。这是经典的可怕钻石问题,您尝试这样做:
人 / \ 学生员工 \ / 能力
但是通过正常的继承,你实际上得到了这个:
人 人 | | 学生员工 \ / 能力因此,在
教职员工实例中实际上有 2 个人,这意味着您将获得 2 个名字。
要获得上面第一个图中的钻石,您需要使用虚拟继承。
class Staff : public virtual Person {
};
class Student : public virtual Person {
};
使用常规的多重继承,您可以获得共享基类的多个副本。 如果需要一个副本,请使用虚拟继承。
在维基百科中解释得很好
class Student : public virtual Person {
};
class Staff : public virtual Person {
};
会得到你所期望的
您分别从两个不同的类继承。
应使用虚拟继承
您遇到了经典的钻石继承问题。由于多重继承在C++的工作方式,Faculty
中实际上有两个不同的name
副本。这通常可以通过使用这样的虚拟继承来解决,因此您只有一个 Person
实例及其成员:
class Student : public virtual Person {
};
class Staff : public virtual Person {
};
我很确定在这种情况下,但是您不想这样做。假设每个Faculty
都是Student
和Staff
成员似乎不合理,因此您不应该以这种方式表示它。Faculty
总是一个Staff
似乎是合理的,所以你可以使用单一继承来模拟这种关系。然后,如果需要,从学生那里分解出(到自由函数或单独的类中)Faculty
中也需要的通用代码。
class Faculty
继承了class Person
的两个子对象,一个通过class Student
,另一个通过class Staff
。
&faculty.Staff::name
返回通过 class Staff
派生的class Person
子对象的地址。
&faculty.Student::name
返回通过 class Student
派生的class Person
子对象的地址。
两者都是不同的子对象,因此地址也不同。
对于多重继承,派生类faculty
有 2 个Person
副本。 第 1 到 Student
和第 2 到 Staff
。
当您引用faculty.Person::name
时,它通过Student
或通过Staff
引用。这是一个模棱两可的情况,甚至不会用 g++ 编译。
在 MSVC 中,似乎由于Faculty
先继承Student
,然后继承Staff
,因此它将faculty.Person::name
称为facutlty ==> Student ==> Person ==> name
。这就是为什么前 2 行的输出相同而第 3 行的输出不同。
有点跑题了,但是....大多数有经验的开发人员都避免多重继承。 它难以维护,充满危险。
- 关于C++中具有多重继承"this"指针的说明
- C++中模板化异常类的多重继承
- 虚拟继承中是否存在多重继承?
- 如何在 c++ 多重继承中调用父非虚函数?
- 多重继承相同的方法名,没有歧义
- 使用enable_if解决多重继承歧义
- 多重继承导致虚假的模糊虚拟函数过载
- 多重继承和访问不明确的元素
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 多重继承问题 C++
- 可视化设计问题 - 多重继承,C++
- C 多重继承,虚拟方法覆盖问题和协变量返回类型
- 如何解决这个C++多重继承类似的问题
- 在 OMNeT++ 中使用多重继承时是否存在任何已知问题
- C++多重继承内存寻址问题
- c++多重继承设计问题
- 多重继承的菱形问题:Gcc / Clang错误,但Visual Studio没有错误
- 一个c++问题,涉及多重继承、模板和静态变量
- 关于C++多重继承的问题
- 比较指针.多重继承问题