0

I have two classes in C++:

class Base
{
  int baseField;
 public:
  Base();
  ~Base();
  T BaseMethod();
  virtual SomeMethod()=0;
};

class Derived : public Base
{
  int derivedField;
 public:
  Derived()
  ~Derived();
  T DerivedMethod();
  virtual SomeMethod() {...}; // Some implementation
};

My question is how it's represented in memory, i.e. where is this pointer, vptr (vtable) fields and methods pointers of this class. Ok, it's compiler dependent, but there is some unwritten standards. I'm most interested in Visual Studio and gcc compilers.

[Edit: I put one virtual method to improve example, there weren't any virtuals before]

Is there some books writing on this theme in details

CppMonster
  • 1,216
  • 4
  • 18
  • 35
  • 5
    Don’t use `C` as a prefix for class names. The practice was created due to a misunderstanding of the MFC naming rules and has no rationale whatsoever. – Konrad Rudolph Jul 16 '13 at 16:28
  • 2
    there is nothing virtual in your class. – user1810087 Jul 16 '13 at 16:28
  • @KonradRudolph no rational whatsoever? That is a strong statement. I don't support this practice but at the very least on could argue helps identify classes with other types at a first glance.. – Justin Meiners Jul 16 '13 at 16:30
  • 2
    I think you're looking for *The Design and Evolution of C++* and *The C++ Object Model*. The latter (especially) describes how things like this work with most C++ compilers, even though it's not actually required by the C++ standard. – Jerry Coffin Jul 16 '13 at 16:31
  • Isn't there empty vtable (rather vptr) in object of class without virtual methods? – CppMonster Jul 16 '13 at 16:32
  • @JustinMeiners Originally, there was no such rationale – that explanation is entirely post-hoc. – Konrad Rudolph Jul 16 '13 at 16:32
  • @CppMonster No, that would waste space in the class. – Neil Kirk Jul 16 '13 at 16:33
  • @JustinMeiners do you have an example of when that could be advantageous? I ask because we have this naming convention at work and I find it most infuriating and completely purposeless :) – juanchopanza Jul 16 '13 at 16:33
  • @juanchopanza I don't think its a good practice but saying it has no rational whatsoever is silly. I just gave an example – Justin Meiners Jul 16 '13 at 16:35
  • @KonradRudolph does it matter if the first people doing it knew that or not? – Justin Meiners Jul 16 '13 at 16:35
  • I'll change my example to allow to get better answers. Sorry for my haste. – CppMonster Jul 16 '13 at 16:38
  • 1
    The `this` pointer isn't stored anywhere; it's the address of the object, passed as an invisible argument to member functions. – Mike Seymour Jul 16 '13 at 16:39
  • @Justin For the purpose of my comment, it does. Yes, I agree that people later invented their (bad) reasons for using the `C` prefix. No, that was not the original intent. Can we leave it at that? – Konrad Rudolph Jul 16 '13 at 16:47

4 Answers4

11

Your classes have no virtual table pointer since they have no virtual functions.

And like you said, even if they had, how virtual functions are implemented is not specified by C++ – every compiler can do it differently, there is no requirement for the existence of a vtable.

In practice, the sane implementation (for single inheritance) is to have a virtual table pointer at the beginning of the class, and after it the normal class members. There is no such thing as “method pointers” – normal member functions are resolved at compile time, and virtual functions have their pointers in the vtable in the order of their declaration.

Here’s an example layout:

struct Base {               + Base ------------+     + Base vtable ----+
    virtual void foo();     | * vptr        ---|---> | * void (*foo)() |
    T bases_field;          | * base_field     |     +-----------------+
};                          +------------------+

struct Derived {            + Derived ---------+     + Derived vtable -+
    T derived_field;        | * CBase instance |---> | * void (*foo)() |
};                          | * derived_field  |     +-----------------+
                            +------------------+

(Not to scale for bytes occupied in memory.)

Each instance thus contains a pointer to a virtual table. Per class, there is only one virtual table. I.e. one shared between all instances of CBase and one shared between all instances of CDerived.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • I found this: http://stackoverflow.com/questions/5684574/understanding-vptr-in-multiple-inheritance, there is a few vtpr for derived classes in the first post – CppMonster Jul 16 '13 at 16:48
  • 1
    @CppMonster That post explicitly examines multiple inheritance, which I’ve explicitly excluded. The reason being that there is no one obvious implementation for multiple inheritance any more, there are several different implementations with different trade-offs (and I don’t remember them). – Konrad Rudolph Jul 16 '13 at 16:52
2

If the class contains at least one virtual function (yours doesn't) and does not use multiple inheritence (that gets complicated), the class usually contains a hidden pointer, to an array of function pointers to the virtual functions. This array is called the virtual function table and shared between all instances of the class. The fields are layed out in the same way as a C struct. The functions you provide are not stored inside the class. Their address is known by the linker, which inserts the call address when the functions are called. The this pointer is not stored inside the class. All non-static class functions, have the this pointer as a hidden parameter. This is pushed on the stack by whatever called the function on the class, which must know the object's address.

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
1
  • The this pointer is not stored. It is used to find the current object but there is no need to store it in the object.

  • Since you don't have any virtual method, there wont be any vptr table.

So in your example, you'll get something which is similar to a C struct with two fields.

hivert
  • 10,579
  • 3
  • 31
  • 56
1

Ok, it's compiler dependent, but there is some unwritten standards. I'm most interested in Visual Studio and gcc compilers.

It's not unwritten at all. Nor is it really compiler dependent. It is ABI dependent. That's a different thing.

MSVC is pretty much the only one to follow a convention not really documented externally, and even then, you could ask the Clang or MinGW developers.

GCC follows the Itanium ABI on most systems, and I believe that ARM has a specified ABI as well. These documents clearly specify what's going on in excruciating detail.

Puppy
  • 144,682
  • 38
  • 256
  • 465