Sizeof Class with Int , Function, Virtual Function in C++

sizeof class with int , function, virtual function in C++?

First off, a virtual function is not a pointer with 8 bytes. In C++ nothing but sizeof(char) is guaranteed to be any number of bytes.

Second, only the first virtual function in a class increases its size (compiler-dependent, but on most - if not all - it's like this). All subsequent methods do not. Non-virtual functions do not affect the class's size.

This happens because a class instance doesn't hold pointers to methods themselves, but to a virtual function table, which is one per class.

So if you had:

class A
{
virtual void foo();
}

and

class B
{
virtual void goo();
virtual void test();
static void m();
void x();
}

you would have sizeof(A) == sizeof(B).

And now:

Why siszeof(A) is 1 and sizeof(C) is 1 too ?

A and C have size 1 just because it's not allowed for a class to be of size 0. The functions have nothing to do with it. It's just a dummy byte.

Why siszeof(H) is 16 but sizeof(G) is 4 ?

G has only one member that accounts for memory - the int. And on your platform, sizeof(int) == 4. H, besides the int, also has a pointer to the vftable (virtual function table, see above). The size of this, size of int and allignment are compiler specific.

Why siszeof(E) is 16 but sizeof(F) is 4 ?

Explained above - non virtual methods don't take up memory in the class.

Why siszeof(D) is 8 but sizeof(E) is 16 ?

D only contains the vftable pointer which is apparently 8 bytes on your platform. E also has an int, and the vftable is aligned to 8 bytes. So it's something like:

class E

4 bytes for int | 4 padding bytes | 8 bytes for vftable pointer |
| x | x | x | x | | | | | v | v | v | v | v | v | v | v |

how to determine sizeof class with virtual functions?

This is of course implementation-dependent. And it would make a terrible interview question. A good C++ programmer can just trust sizeof to be right and let the compiler worry about those vtable things.

But what's going on here is that a typical vtable-based implementation needs two vtables in objects of class C or D. Each base class needs its own vtable. The new virtual methods added by C and D can be handled by extending the vtable format from one base class, but the vtables used by A and B can't be combined.

In pseudo-C-code, here's how a most derived object of type D looks on my implementation (g++ 4.4.5 Linux x86):

void* D_vtable_part1[] = { (void*) 0, &D_typeinfo, &A::f1, &C::f3, &D::f4 };
void* D_vtable_part2[] = { (void*) -4, &D_typeinfo, &B::f2 };

struct D {
void** vtable_A;
void** vtable_B;
};

D d = { D_vtable_part1 + 1, D_vtable_part2 + 1 };

Size of class with virtual function

You're working on a platform where pointers are aligned to 8 bytes. Since the virtual table pointer is typically the first thing in the layout of an object, it too must be aligned to 8 bytes. So padding 4 bytes are inserted after the int member, that's why you get a size of 16 (8 bytes for the vf table pointer, 4 for the int and 4 padding bytes).

c++ sizeof() of a class with functions

The class contains no data members, so it's empty. The standard demands that every class have at least size 1, so that's what you get. (Member functions aren't physically "inside" a class, they're really just free functions with a hidden argument and a namespace and access control.)

sizeof derived class with virtual base and virtual function

Pointer denotes the virtual function table of Base class--4 bytes

Pointer denotes the virtual function Func2() which only belongs to
class Derived--4 bytes (as far as I'm concerned, derived class which
has no non-virtual base classes and gets its unique virtual functions
should has its own virtual table)

Ah, I see the problem now. That's not quite how virtual function tables work. When Base is defined, the compiler notices it requires a virtual table, and generates a virtual table for Base, with one pointer (Func), which points to the Base::Func implementation. When Derived is defined, the compiler notices it inherits from Base, and generates a function table for Base that has two pointers, Func points to Derived::Func, and Func2 points to Derived::Func2.

Then, if an instance of Base is created, it's function table pointer that you mention points at the Base table, and any calls to Func will be redirected to Base::Func.

If an instance of Derived is created, it's internal Base object's virtual function table pointer will point at the Derived table instead. Base only knows how to access the Func pointer, but that Func pointer points at Derived::Func now, and so that's what get's called. It doesn't realize it's pointing at a different table. In code, it might look more like this:

using voidFunctionType = void(*)();

struct BaseVTable {
voidFunctionType Func;
}BaseVTableGlobal;

struct Base {
Base() :vTable(&BaseVTableGlobal) {}
void Func() {vTable->Func();}

BaseVTable* vTable; //4 bytes
int BaseValue; //4 bytes
}; //total is 8 bytes

struct DerivedVTable : public BaseVTable {
voidFunctionType Func;
voidFunctionType Func2;
}DerivedVTableGlobal;

//inherits 8 bytes, +4 for virtual inheritance = 12
struct Derived : virtual public Base {
Derived() :Base() {vTable = &DerivedVTableGlobal;} //the shared vTable points at DerivedVTableGlobal
void Func() {vTable->Func();} //base knows about Func, so this is easy
void Func2() {((DerivedVTable*)vTable)->Func2();} //base doesn't know about Func2

int DerivedValue; //4 bytes
}; //16 bytes total

So XCode is right. Derived is "hijacking" Bases virtual function table, and in fact, that's exactly how virtual functions do their magic.

(Assumptions everywhere, none of this is well-defined, virtual inheretence complicates things, etc etc etc)

Size of class with virtual function adds extra 4 bytes

I assume you are compiling on 64bit machines since size of int is 4bytes.Typically for 64bit machines pointer size will be 8 bytes and int size is 4 bytes.To satisfy Data Alignment requirement to save read cycles
compiler adds extra 4 bytes(padding) hence result is 16bytes where as actual required size is 12 bytes.

Size of derived class in virtual base class function

You can use the CRTP idiom to do this.
https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c
The idea is the parent class is a template, so you can have access to the type of the child class directly in it.
With that, you'll be able to remove all "PrintSize" from child class.

Example :

template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};

class B : public A<B> {
int a, b, c;
public:
B() {}
};

class C : public A<C> {
public:
C() {}
};

int main() {
C objc;
B objb;

objc.PrintSize();
objb.PrintSize();
}

The output is :

8

20



Related Topics



Leave a reply



Submit