This article is the collection of concept I have acquired while introducing myself to C++ by googling here & there. This material is also not in order. I have just collected the answer to my quick question. And write it down here. But one thing I can assure you is that once you go through this article. You can connect many broken thought of understanding on what runs “Inside the C++ object model”. And why people call it as it runs C internally.
Note: In addition, here I have not considered name mangling & other compiler attributes for simplicity. Also not shown how object memory layout created. So, I have discussed it here. Code augmentation depends on compiler implementation, there is no such standard define.
Default Member-Functions Created by the Compiler Inside the C++ Object Model
Suppose you have declared class like:
|
|
- The compiler will probably synthesize this class as:
- So by default compiler will generate:
- default constructor
- copy constructor
- copy-assign operator
- destructor
- move constructor
- move-assign operator
Note: This stands true till C++ 14.
- The compiler creates all default/implicitly-declared member-functions when it needed. A compiler cannot create default member-functions when it’s no use.
How C++ Object Model Used in Function?
- Given the following function, where
class X
defines a copy constructor, virtual destructor, and virtual functionfoo()
- The probable compiler transformation would be:
|
|
- This is how the object-oriented paradigm converted into the procedure-oriented paradigm.
How Class/Object-Oriented Code Transformed Into Sequential Code?
- Let’s take the following example to understand it:
- The compiler treats this as :
- As you can see above, objects & methods are a separate entity. An object only represents data members.
- Therefore, all the methods in class/struct contain implicit
this
pointer as the first argument using which all non-static data members are accessed. - Static data members are not part of class/struct. Because it usually resides in a data segment of memory layout. So it accesses directly(or using segment registers).
- So this is the reason if you print the size of the above class. Hence, It prints 4 because all methods are a separate entity which operates on the object by using implicit
this
pointer.
How & Where Constructor Code Transform/Synthesize With Inheritance & Composition Class?
|
|
- Compiler augmented
Bar
constructor would look like:
- Similarly, multiple class member objects require a constructor initialization. The language specifies that the constructors would be invoked in the order of member declaration within the class. This is accomplished by the compiler.
- But, if an object member does not define a default constructor, a non-trivial default constructor synthesizes by a compiler for respective classes.
- Moreover, in the case of inheritance, the constructor calling sequence starts from base(top-down) to derived manner. Constructor synthesis & augmentation remain same as above.
- So in the above case, if you derive
Bar
fromBase
then constructor calling sequence would beBase
->Foo
->Bar
.
How & Where Destructor Code Transform/Synthesize With Inheritance & Composition Class?
- In case of the destructor, calling sequence is exactly the reverse that of a constructor. Like in the above case it would be
Bar
->Foo
->Base
. Synthesis & augmentation remain same as above. Access and all other things remain the same.
How & Where Virtual Table Code Will Be Inserted?
- The virtual table code will be inserted by the compiler before & after the user-written code in constructor & destructor. That too on demand of user implementation.
- Additionally, for the question “How virtual table code will be inserted”, my answer is “this is purely compiler dependent”. C++ standard only mandates behaviour. Although this would not be complex. It probably would look like:
|
|
- By the way, I have written a more detailed article on virtual keyword here.