Why is a vptr required when the derived class doesn't override the virtual function?
Asked Answered
A

4

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?

Anvil answered 2/2, 2012 at 9:11 Comment(8)
did you ever hear about overloading in C++?Thermochemistry
@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).Zoosporangium
for your kind information, these are not overloaded function.Anvil
This code actually has hiding issue: der::fn(char) hides base::fn(int).Zoosporangium
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.Purposive
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 elseThermochemistry
@KamilKlimek: Overloading is not across classes, the compiler interprets it correctly, this is well defined in the standard.Purposive
Now i know it, thank you. BTW question is about VTABLES, but i have better example of what actually happens here: pastebin.com/waWQVDu4 thats why I totaly missunderstood the question.Thermochemistry
P
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.

Purposive answered 2/2, 2012 at 9:13 Comment(1)
But in this example, all the code is in the same module and the compiler could know.Aida
A
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.

Aida answered 2/2, 2012 at 9:27 Comment(4)
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; ?Thermochemistry
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.Thermochemistry
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.Aida
I think Als gave answer, that simply prooves compiler can't tell it for sureThermochemistry
T
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.

Torsi answered 23/4, 2016 at 7:42 Comment(0)
P
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.

Pekingese answered 2/2, 2012 at 9:18 Comment(7)
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?Purposive
If none of the derived classes ever override the virtual fucntnAida
@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.Pekingese
@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?"Purposive
@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...Pekingese
@LuchianGrigore: That is almost what my answer says :)Purposive
@Als and I upvoted... I just seemed obvious to me, that's why I left it out.Pekingese

© 2022 - 2024 — McMap. All rights reserved.