0

我不是 C++ 专业人士,我主要从事 Java 和 C#。今天老师说了一句话让我很困惑。我试图通过做一些研究来验证信息,但我最终更加困惑。

假设我有 A 类和 B 类。A 类是基类,B 是从 A 派生的。

现在我已经知道,当创建 B 类的对象时,会调用 A 类的构造函数,然后调用 B 类的构造函数。同样,当 B 类的对象被销毁时,会调用 B 类的析构函数,然后调用 A 类的析构函数。

到目前为止,我的理解是 B 类包含 A 类中的所有内容,除了它的构造函数和析构函数。我认为当构建 B 类的对象时,在内存中只创建了一个对象(A 和 B 类型)。

现在我的老师说,当构建 B 时,会创建 2 个单独的对象并以某种方式“链接”在一起:A 类中的一个,然后 B 类中的一个。这两个对象都将存在于内存中,直到调用 B 类对象的销毁. 那么 B 类对象将在 A 类对象被销毁之前被销毁。

哪一个是正确的?

ps对不起,如果我的英语一般,那不是我的母语...

编辑:生病尝试改写:

我认为:B类包含A类的所有属性和方法。当我从B类创建一个对象时,内存中只存在1个对象。调用类 A 的构造函数只是为了初始化我的对象中最初来自类 A 的部分。

老师说:当我从B类创建一个对象时,在内存中创建了2个对象。当我命令销毁我的对象时,首先销毁内存中的 B 类对象,然后销毁同样保留在内存中的 A 类对象。老师永远无法阐明 B 类对象如何能够使用 A 类对象的方法和属性。

对我来说,这似乎也意味着在内存中的某个地方存在一个我不知道并且我几乎无法控制的“幽灵对象”。

4

1 回答 1

1

根据http://www.vishalchovatiya.com/memory-layout-of-cpp-object/#Layout_of_C_Object_With_Inheritance

这两个类:

class X {
    int     x;
    string str;
public:
    X() {}
    virtual ~X() {}
    virtual void printAll() {}
};
class Y : public X {
    int     y;
public:
    Y() {}
    ~Y() {}
    void printAll() {}
};

将在内存中表示,因此 Y 的内存布局包含基类的数据成员,然后是派生类的数据成员:

      |                              |          
      |------------------------------| <------ Y class object memory layout
      |          int X::x            |
stack |------------------------------|
  |   |              int string::len |
  |   |string X::str ----------------|
  |   |            char* string::str |         
 \|/  |------------------------------|      |-------|--------------------------|
      |           X::_vptr           |------|       |       type_info Y        |
      |------------------------------|              |--------------------------|
      |          int Y::y            |              |    address of Y::~Y()    |
      |------------------------------|              |--------------------------|
      |               o              |              | address of Y::printAll() |
      |               o              |              |--------------------------|
      |               o              |              
------|------------------------------|--------
      |           X::X()             | 
      |------------------------------|       |   
      |           X::~X()            |       |
      |------------------------------|       | 
      |         X::printAll()        |      \|/ 
      |------------------------------|  text segment
      |           Y::Y()             |
      |------------------------------|
      |           Y::~Y()            |
      |------------------------------|
      |         Y::printAll()        |
      |------------------------------|
      |      string::string()        |
      |------------------------------|
      |      string::~string()       |
      |------------------------------|
      |      string::length()        |
      |------------------------------|
      |               o              |
      |               o              |
      |               o              |
      |                              |

同一页面还具有其他场景的内存布局,包括多重继承和虚拟继承。

于 2021-11-18T01:02:45.543 回答