0

Im not a C++ pro, i've done mostly Java and C#. A teacher said something that confused me today. I've tried to validate the info by doing some research, but i ended up even more confused.

Lets say i have class A and class B. Class A is the base class and B is derived from A.

Now i already know that when an object of class B is made, the constructor from class A is called, and then the constructor from classe B is called. Similarly, when and object of class B is destroyed, the class B destructor is called, and then the ones from class A.

So far, my understanding was that Class B contains everything from class A except it's constructors and destructors. I thought that when an object from class B was built, only one object (of both types A and B) was created in memory.

Now my teacher is saying that when B is built, 2 separate objets are created and somehow "linked" together: one of class A and then one of class B. Both objects would exist in memory until the destruction of the class B object is called. Then the class B objet would be destroyed before the class A object is destroyed.

Which one is correct?

ps sorry if my english is so-so, it's not my native language...

Edit: ill try to rephrase:

I think: Class B contains all attributes and methods of class A. When i create an object from class B, only 1 object exists in memory. The constructor of class A is called just to initialize the part of my object that was originally from class A.

The teacher said: When i create an object from class B, 2 objects are created in memory. When i command the destruction of my object, the class B object that is in memory is destroyed first, and then the class A object that is also remaining in memory is destroyed. The teacher was never able to clarify how the class B object is able to use the methods and attributes of the class A object.

For me, this also seems to imply that there is a "ghost object" somewhere in memory that i am unaware of and of which i have almost no control.

  • 2
    You say that your teacher said, *2 separate objets are created and somehow "linked"*. Not sure what 'your teacher' means by that ... it certainy doesn't sound right. Can you clarify? – Adrian Mole Nov 17 '21 at 23:35
  • 2
    It might help if instead of "A" and "B", you rename your class A to "AppleCore" and your class B to "Apple". Now when you create an Apple object (which subclasses AppleCore), you are implicitly creating an AppleCore as the first/innermost part of the Apple. – Jeremy Friesner Nov 17 '21 at 23:37
  • 1
    Side note: [The C++ definition of an object](https://en.cppreference.com/w/cpp/language/object) is a bit weird if you're coming in from other languages. – user4581301 Nov 17 '21 at 23:38
  • 1
    1 sec, ill add a "rephrase" in my op – Frédéric Bélanger Nov 17 '21 at 23:44
  • 1
    Your teacher sounds like they're taking a much more prototype-oriented view that would make more sense in Javascript or Lua (though it still isn't strictly true in either of those), but certainly isn't accurate in C++. – Silvio Mayolo Nov 17 '21 at 23:44
  • 3
    Read the __Subobjects__ section from here - https://en.cppreference.com/w/cpp/language/object _"...An object can contain other objects, in which case the contained objects are nested within the former object. An object a is nested within another object b if..."_ and _"...An object can have subobjects. These include...base class subobjects..."_ – Richard Critten Nov 17 '21 at 23:48
  • @RichardCritten tks, ill try to read that tomorrow and give you some feedback. – Frédéric Bélanger Nov 18 '21 at 00:02
  • 1
    I found this: http://www.vishalchovatiya.com/memory-layout-of-cpp-object/#Layout_of_C_Object_With_Inheritance it may help... – Jerry Jeremiah Nov 18 '21 at 00:04
  • 2
    I'd say both of you are correct. Two objects can overlap (subobjects, as per @RichardCritten's quotes). The 'linking' is usually implicit (B knows at what offset A is located), except when it's not (virtual inheritance). – Yakov Galka Nov 18 '21 at 00:06
  • 1
    A compiler may choose to create two objects or one object. If `class A` is not used for other purposes, the compiler can drop the isolated `class A` and merge `class A` into `class B`; thus producing one object. Depends on the compiler and the optimization settings. – Thomas Matthews Nov 18 '21 at 00:19
  • @YakovGalka yeah, from the memory layout i got here, it seems the attributes and methods of class A are not transferred to class B. A kind of "anonymous" object of type A is created and added to class B as a subobject. It appears that when i call a class A method from my "B object", an "A::" is implicitly added. My teacher was correct. Good thing i decided to verify my belief before startign an argument with him :) – Frédéric Bélanger Nov 18 '21 at 00:25
  • @JerryJeremiah would you mind writing your comment as an answer so i can flag it pls. It's what i was looking for :) – Frédéric Bélanger Nov 18 '21 at 00:27
  • Link-only answers attract downvotes. I will make an answer. – Jerry Jeremiah Nov 18 '21 at 00:51

1 Answers1

1

According to http://www.vishalchovatiya.com/memory-layout-of-cpp-object/#Layout_of_C_Object_With_Inheritance

These two classes:

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

Would be represented in memory so that the memory layout of Y contains the data members of the base class followed by the data members of the derived class:

      |                              |          
      |------------------------------| <------ 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              |
      |                              |

That same page also has memory layouts of other scenarios, including multiple inheritance and virtual inheritance.

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32