关于 C++ 中多重继承的问题?

发布于 2024-11-08 04:45:17 字数 1046 浏览 0 评论 0原文

我有以下代码:

#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 1Line 2中的地址与Line 3不同,而Student和Staff都从Person继承名称?

I have the following code:

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

When executed, the program gives the results:

Address of faculty.Person::name: 0012FF20 // **Line 1**
Address of faculty.Student::name: 0012FF20 // **Line 2**
Address of faculty.Staff::name: 0012FF3F // **Line 3**

I don't get it. Why the address in Line 1 and Line 2 is different from Line 3, while both Student and Staff inherits name from Person?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

画离情绘悲伤 2024-11-15 04:45:46

有点偏离主题,但是......大多数有经验的开发人员都会避免多重继承。它很难维护并且充满危险。

A bit off topic but....Most experienced developers avoid multiple inheritance. It is difficult to maintain and fraught with peril.

歌入人心 2024-11-15 04:45:45

classFaculty继承了classPerson的两个子对象,一个通过classStudent继承,另一个通过classStaff继承。

&faculty.Staff::name 返回通过class Staff 派生的class Person 的子对象的地址。

&faculty.Student::name 返回通过 class Student 派生的 class Person 的子对象的地址。

两者都是不同的子对象,因此地址也不同。

class Faculty inherits two sub objects of class Person, one through class Student and another through class Staff.

&faculty.Staff::name returns address of the sub object of class Person derived through class Staff.

&faculty.Student::name returns address of the sub object of class Person derived through class Student.

Both are different sub objects and hence the different address.

如痴如狂 2024-11-15 04:45:45

对于多重继承,您的派生类faculty有2个Person副本。第一名至学生,第二名至员工

当您引用 faculty.Person::name 时,它是通过 Student 或通过 Staff 引用的。这是一种不明确的情况,甚至无法用g++编译。

在MSVC中,似乎由于Faculty首先继承Student,然后继承Staff,所以它引用了faculty.Person::name > 作为功能==>学生==>人物==>名称。这就是为什么前两行的输出相同而第三行的输出不同。

For multiple inheritance your derived class faculty has 2 copies of Person. 1st through Student and 2nd through Staff.

When you refer faculty.Person::name, it refers either via Student or via Staff. This is an ambiguous situation and even will not compile with g++.

In MSVC, it seems that since Faculty inherits Student first and then Staff, it's referring faculty.Person::name as facutlty ==> Student ==> Person ==> name. That's why output of first 2 lines are same and 3rd line is different.

水染的天色ゝ 2024-11-15 04:45:44

您分别从两个不同的类继承。

你应该使用虚拟继承

you are inheriting from the two different classes separately.

you should use virtual inheritance

怎樣才叫好 2024-11-15 04:45:44

您遇到了经典的钻石继承问题。由于 C++ 中多重继承的工作方式,Faculty 中实际上有 两个 个不同的 name 副本。这通常可以通过使用像这样的虚拟继承来解决,因此您只有一个 Person 及其成员的实例:

class Student : public virtual Person {
};
class Staff : public virtual Person {
};

我很确定在这种情况下,但您不想这样做。假设每个Faculty同时也是StudentStaff成员似乎并不合理,因此您不应该在此表示它方式。 Faculty 似乎总是 Staff,因此您可以使用单一继承来建模该关系。然后,如果需要,从学生中提取出(分解为自由函数或单独的类)Faculty 中也需要的通用代码。

You've encountered the classic diamond inheritance problem. Due to the way multiple inheritance work in C++ there are actually two distinct copies of name in Faculty. This can typically be solved by using virtual inheritance like this, so you only have one instance of Person and its members:

class Student : public virtual Person {
};
class Staff : public virtual Person {
};

I'm pretty sure in this case however you don't want to do this. It doesn't seem reasonable to assume that every Faculty is also a Student AND a Staff member, so you shouldn't represent it in this way. It seems plausible that a Faculty would always be a Staff, so you could use single inheritance to model that relationship. Then if needed, factor out (into free functions or a separate class) the common code from student that's also needed in Faculty.

苦行僧 2024-11-15 04:45:42

通过常规多重继承,您可以获得共享基类的多个副本。如果您想要一份副本,请使用虚拟继承。

Wikipedia 中有很好的解释

class Student : public virtual Person {
};
class Staff : public virtual Person {
};

会给你你所期望的

With regular multiple inheritance you get multiple copies of shared base classes. If you want one copy, use virtual inheritance.

Explained well in Wikipedia

class Student : public virtual Person {
};
class Staff : public virtual Person {
};

Will get you what you expected

最近可好 2024-11-15 04:45:41

当您以这种方式进行多重继承时,您将获得祖父母类的两个副本。这是经典的可怕的钻石问题,其中你尝试这样做:

        Person
       /       \
     Student  Staff
       \       /
        Faculty

但是通过正常的继承,你实际上得到了这个:

    Person   Person
      |        |
     Student Staff
       \       /
        Faculty

所以在Faculty的实例中确实有2个Person,这意味着你会得到2个名字。

要获得上面第一个图中的菱形,您需要使用 虚拟继承

class Staff : public virtual Person {
};
class Student : public virtual Person {
};

When you do multiple inheritance this way you get two copies of the grandparent class. This is the classic dreaded diamond problem, where you try to do this:

        Person
       /       \
     Student  Staff
       \       /
        Faculty

but through normal inheritance you actually get this:

    Person   Person
      |        |
     Student Staff
       \       /
        Faculty

So there's really 2 Person's in an instance of Faculty, meaning youll get 2 names.

To get the diamond in the first diagram above, you want to use virtual inheritance.

class Staff : public virtual Person {
};
class Student : public virtual Person {
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文