8
class base {
public:
    void virtual fn(int i) {
        cout << "base" << endl;
    }
};

class der : public base{
    public:
    void  fn(char i) {
        cout << "der" << endl;
    }
};

int main() {

    base* p = new der;
    char i = 5;
    p->fn(i);
    cout << sizeof(base);
    return 0;
}

Here signature of function fn defined in base class is different from signature of function fn() defined in der class though function name is same. Therefore, function defined in der class hides base class function fn(). So class der version of fn cannot be called by p->fn(i) call; It is fine.

My point is then why sizeof class base or der is 4 if there is no use of VTABLE pointer? What is requirement of VTABLE pointer here?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
user966379
  • 2,823
  • 3
  • 24
  • 30
  • did you ever hear about overloading in C++? – Kamil Klimek Feb 02 '12 at 09:14
  • @KamilKlimek: Overloading is the act of declaring multiple functions with different signatures. What you probably mean is overriding (which is reimplementing methods in derived classes). – Frerich Raabe Feb 02 '12 at 09:16
  • for your kind information, these are not overloaded function. – user966379 Feb 02 '12 at 09:16
  • This code actually has hiding issue: `der::fn(char)` hides `base::fn(int)`. – Frerich Raabe Feb 02 '12 at 09:17
  • This is *function hiding*, *Function overriding* requires following to be satisfied: 1. Presence of `virtual` keyword & 2. Matching function parameters with the exception of *co-variant* return types. – Alok Save Feb 02 '12 at 09:21
  • I didn't mean override, but overload. For a first look der::fn(char) looks for me as overloaded fn(int). But it seems that compiler thinks something else – Kamil Klimek Feb 02 '12 at 09:47
  • 1
    @KamilKlimek: Overloading is not across classes, the compiler interprets it correctly, this is well defined in the standard. – Alok Save Feb 02 '12 at 09:57
  • Now i know it, thank you. BTW question is about VTABLES, but i have better example of what actually happens here: http://pastebin.com/waWQVDu4 thats why I totaly missunderstood the question. – Kamil Klimek Feb 02 '12 at 10:12

4 Answers4

7

Note that this is highly implementation dependent & might vary for each compiler.

The requirement for presence of vtable is that the Base class is meant for Inheritance and extension, and a class deriving from it might override the method.

The two classes Base and Derived might reside in different Translation Unit and the compiler while compiling the Base class won't really know if the method will be overidden or not. So, if it finds the keyword virtual it generates the vtable.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

The compiler cannot optimize out vtable member variable out of 'base' class, because there could be another source file within the same or another project which would contain the following:

struct ived : base {
    ived() : p(new char[BIG_DATA_SIZE]) {}
    virtual ~ived();
    virtual void fn(int);
private:
    char* p;
};

The destructor and fn could be implemented somewhere else:

ived::~ived() { delete[] p; }

void ived::fn(int) {
    cout << "ived" << endl;
}

And somewhere in another place there could be code like this:

base* object = new ived;
ived->fn(0);
delete object;
cout << sizeof(base) << endl;

So, there would be two problems: virtual function ived::fn not called, virtual destructor not called, so BIG_DATA_SIZE not deleted. Otherwise, sizeof(base) here would be different. That is why compilers always generate vtable for any class with a virtual member function or a virtual base class.

Regarding calling destructors in derived classes, it must be considered as a must: if you have any class with any virtual function, that class shall also declare a virtual destructor.

Alan Milton
  • 374
  • 4
  • 13
1

The vtable is usually not only used for virtual functions, but it is also used to identify the class type when you do some dynamic_cast or when the program accesses the type_info for the class.

If the compiler detects that no virtual functions are ever overridden and none of the other features are used, it just could remove the vtable pointer as an optimization.

Obviously the compiler writer hasn't found it worth the trouble of doing this. Probably because it wouldn't be used very often, and because you can do it yourself by removing the virtual from the base class.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • A virtual b(int), B: public A - no override, C: public B override b(int), D: public C - no override. And how do you except compiler to behave in this case? Where should be vtable and where shouldn't? if I B * instance = new D; ? – Kamil Klimek Feb 02 '12 at 10:40
  • Also what if it is used as plugin factory? It has no physical way to know, if there will or will not be inherited class that overrides virtual method. – Kamil Klimek Feb 02 '12 at 10:45
  • If there is an override anywhere, the vtable will have to be there everywhere, because there can only be one version of each class. It is just if (big if!) the compiler can tell for sure it is not needed, that it can be optimized out. – Bo Persson Feb 02 '12 at 11:44
  • I think Als gave answer, that simply prooves compiler can't tell it for sure – Kamil Klimek Feb 02 '12 at 11:48
0

Inheritance is a is-a relationship. der is-a base. base has size 4, der will have at least size 4. vftableptr is a member of base, it will be a member of der.

base has a virtual method, so it will have a pointer to the virtual table, regardless of whether you use it or not.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • You are missing the point, the Q OP asking is *why is size of the Base class `4`?* and not *Why size of the derived class is `4`?* – Alok Save Feb 02 '12 at 09:19
  • If none of the derived classes ever override the virtual fucntn – Bo Persson Feb 02 '12 at 09:21
  • @Als I was confused because it seems pretty straightforward to me. It has a virtual method, why shouldn't it have a pointer to the vtable? I edited my answer to reflect this. – Luchian Grigore Feb 02 '12 at 09:25
  • @LuchianGrigore: I understand,just to clarify a bit more on the question.The OP says *"If the Base class virtual method is not overridden by any derived class(this implies there will not be any dynamic dispatch needed at all), then why does the compiler not optimize and remove the unnecessary overhead of creating a vtable?"* – Alok Save Feb 02 '12 at 11:01
  • @Als ok I see. I can't see a way for the compiler to know whether the base class is extended, be it in the current or a different module... – Luchian Grigore Feb 02 '12 at 11:42
  • @LuchianGrigore: That is almost what my answer says :) – Alok Save Feb 02 '12 at 11:43
  • @Als and I upvoted... I just seemed obvious to me, that's why I left it out. – Luchian Grigore Feb 02 '12 at 11:45