14

I was asked this interview question today!! (it was a really awkward telephonic interview..):

What is the difference between the vtable for a class with virtual functions and a class with pure virtual functions?

Now, I know the C++ standard doesn't specify anything about vtables, or even the existence of a v-table ..however theoretically speaking what would the answer be?

I blurted out that the class with a pure virtual function could have a vtable and its vtable entry for the pure virtual function will point to the derived class implementation. Is this assumption correct? I did not get a positive answer from the interviewer.

Will a hypothetical compiler create a vtable for a class with only pure virtual functions? What if the class contains pure virtual functions with definitions? (as shown in : http://www.gotw.ca/gotw/031.htm).

user7
  • 2,339
  • 5
  • 25
  • 29
  • telephone interview? didn't you have access to google? – Mitch Wheat Oct 03 '11 at 14:18
  • 4
    if I was a manager and I heard typing over a phone interview I think I'd fail the person instantly :p – John Humphreys Oct 03 '11 at 14:20
  • I didn't say it was a good idea, or that I agree with doing it. Let's face it, if a candidate isn't smart enough to disguise the fact they are using google, would you employ them? – Mitch Wheat Oct 03 '11 at 14:20
  • Disguising their actions is far worse than using google. I wonder how many successful engineers make it through a week without using google? How about a day? Acting upon the answer to the question would not make you a good engineer either, quite the contrary. – Tom Kerr Oct 03 '11 at 14:47
  • I've used google on phone interviews before and I usually end up feeling dirty. I'd rather just say, "I dunno, I'd have to look that up." – gred Oct 03 '11 at 19:07

3 Answers3

24

In the case of non-pure virtual functions, each entry in the vtable will refer to the final-overrider or a thunk that adapts the this pointer if needed. In the case of a pure-virtual function, the entry in the vtable usually contains a pointer to a generic function that complains and aborts the program with some sensible message (pure virtual function called within this context or similar error message).

Will a hypothetical compiler create a vtable for a class with only pure virtual functions?

Yes, it will, the difference will be in the contents stored in the table, not in the shape of the table. In a simplistic approach, a NULL pointer for pure virtual functions, non-NULL for virtual functions. Realistically, a pointer to a generic function that will complain and abort() with usual compilers.

What if the class contains pure virtual functions with definitions?

This will not affect the vtable. The vtable is only used for dynamic dispatch, and a call will never be dynamically dispatched to the definition of a pure virtual function (i.e. you can only manually dispatch to the pure virtual function by disabling dynamic dispatch qualifying the name of the type: x.base::f() will call base::f even if it is pure-virtual, but x.f() will never be dispatched to base::f if it is pure virtual.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • You need the thunk only on multiple inheritance, don't you? On single inheritance, base and derive start at the same location, so there's no need to adapt `this`. – Eran Oct 03 '11 at 14:23
  • @eran: right, in a linear inheritance hierarchy all objects with virtual functions will likely have the same address. – Matthieu M. Oct 03 '11 at 14:27
  • @MatthieuM: "in a linear inheritance hierarchy all objects with virtual functions will likely have the same address" : Why? – user7 Oct 03 '11 at 14:55
  • @MatthieuM.: *simply a null pointer* fits the standard, but all implementations I know add the helper function. It is somehow *low hanging fruit* to improve the quality of implementation, why just trigger a crash when you can provide information on what went wrong *and* crash? – David Rodríguez - dribeas Oct 03 '11 at 15:13
  • @user7: The *thunk* is required only in those cases where the pointer to the base and derived classes are different. In a single inheritance relationship, the `base` subobject is aligned with the `derived` subobject, and that means that `(void*)static_cast(p) == (void*)p` where `p` is a pointer to derived (the location in memory of `base` and `derived` coincides). When you have multiple inheritance, only one of the bases can be aligned with the `derived` object, so for one of the multiple bases the pointers coincide, but for the rest you need to correct the `this` pointer. – David Rodríguez - dribeas Oct 03 '11 at 15:15
  • @DavidRodríguez-dribeas: I seem to remember crashes with gcc 3.4 (yes, it's old) in release mode, maybe wrong, it was some times ago. – Matthieu M. Oct 03 '11 at 15:28
1

An implementation can do pretty much anything in such cases, because if your code ends up calling a pure virtual function in a context where dynamic resolution is required, and it would resolve to a pure virtual function, the behavior is undefined. I've seen several different solutions: the compiler inserts the address of a function which terminates with an error message (the preferred solution from a quality of implementation point of view), the compiler inserts a null pointer, or the compiler inserts the address of the function from some derived class. I've also seen cases where the compiler will insert the address of the function if you provide an implementation. The only correct answer to the question is that you can't count on any particular behavior.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

I can tell you that "pure" abstract classes (classes with only pure virtual functions) are used by Microsoft (and MS VC++) for their COM interfaces. Perhaps he was speaking of it. The "internal" representation of a COM is a pointer to a vtable. Pure abstract classes in MS VC++ are implemented in the same way, so you can use them to represent COM objects. Clearly if you class has other virtual functions, you can't simply overwrite its vtable with the COM vtable :-)

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • IIRC, an abstract class is a class with one or more pure virtual method, whereas an interface class is an abstract class with only pure virtual methods and no member variables. Now, I never found the terms "abstract" and "interface" codified in C++. I'm extrapolating from C# and Java. – paercebal Oct 03 '11 at 14:27
  • @paercebal But there aren't `interface`s in C++ :-) The "correct" term is `pure abstract class` (and I forgot to write it :-) ) – xanatos Oct 03 '11 at 14:30
  • `But there aren't "interfaces" in C++` : More specifically, the `interface` keyword does not exist in C++. The concept does exist, is supported by the language, and is even extended when compared to Java's `interface`. – paercebal Oct 03 '11 at 19:56
  • @paercebal Observe how I formatted the `interface`s in my comment :-) The trick was there. You can have interfaces even without having pure abstract classes. Interfaces exist primarily in the mind of the programmer. A class where each virtual method throws and must be overloaded to do something is an interface for me. You don't need language support that isn't polymorphism. You can use COM with C, and C doesn't even have classes, and COM is based on interfaces. As I said, interfaces are in the mind of the programmer. The language can only flag as an error instantiating them. – xanatos Oct 03 '11 at 20:00