I am interested to know what the reason is for there to be no non-member virtual functions in C++. Especially considering the fact that it simply increases code layers when you want to achieve it, since you can define a virtual member-function and then call it from a non-member function.
EDIT:
Just for reference, you can do that:
struct Base
{
virtual void say() const
{
std::cout << "Base\n";
}
};
struct Derived : public Base
{
void say() const final
{
std::cout << "Derived\n";
}
};
void say(Base* obj)
{
obj->say();
}
say(static_cast<Base*>(new Derived()));
Edit 2:
And there are indeed cases where you want virtual polymorphism, since you can have the case below which doesn't work in a similar fashion, since it prints Base whereas if you were to call it with the above code, in a similar fashion it will print Derived. I believe this summarizes the crux of the problem.
void say(Base* obj)
{
std::cout << "Base\n";
}
void say(Derived* obj)
{
std::cout << "Derived\n";
}
say(static_cast<Base*>(new Derived()));
A non-member function does not require an implicit this pointer in order to invoke it.
But virtual functions require a this pointer (i.e. an object instance) in order for polymorphism to work.
And there's the contradiction: so it's not possible to have a polymorphic non-member function.
Having virtual non-member functions is technically challenging to compile.
Virtual functions are usually implemented with a vtable. Classes with virtual member functions store a pointer to that vtable, and that vtable has all the requisite functions added to it. When a virtual function is invoked, the exact function to invoke is looked up in the vtable.
Consider this: I'm writing a library in C++. For user convenience, and to reduce compiletimes, the library is distributed as:
the header files for the library
binary files that provide the implementation of the functions defined in the headers.
So what's the problem?
These binary files will also contain the vtables for any classes with virtual functions within the header files. In order to add virtual functions to a base class, the compiler will have to read and process the binary representation of the library files, modifying the vtables to add the necessary functions.
This would greatly increase the complexity of linking (making the compiler partially responsible for doing so), and it would bloat executable size (any dynamically loaded libraries would have to be statically linked, since the compiler might not have permission to modify their contents).
Are there technical work-arounds?
Yes, although it would require the implementation of the class to be present in the header file, like a template. Alternatively, the new module system could provide a way to implement this feature by forgoing the need to have separate implementation files.
Even then, it would require a lot of work on the part of compiler developers, and there has not been much demand for this feature. The main benefit this feature provides is being able to quickly and easily overload functions for specific derived classes, which itself is considered something of a code smell (since you'd come close to breaking encapsulation - a library writer writing a function that returns a pointer to a base class may want to change which derived class it returns, for example).
When you want to use polymorphism in free functions you basically have two options. Either you overload the function or you call virtual functions:
#include <iostream>
struct base {
virtual void func() = 0;
};
struct foo : base { void func() { std::cout << "foo\n"; } };
struct bar : base { void func() { std::cout << "bar\n"; } };
void f(foo& f) { f.func(); }
void f(bar& f) { f.func(); }
void g(base& b) { b.func(); }
int main() {
foo a;
bar b;
f(a);
f(b);
g(a);
g(b);
}
Considering that the main difference to member functions is the implicit this parameter, g is actually rather close to what I'd call a "virtual free function". However, other than that there are no virtual non-member functions in C++.
I am confused how vptr resolves virtual function call at run time if there are more virtual functions in a class. Who takes care of that. And who creates vtable . is it compiler?
Consider code something like this:
class A {
int x;
public:
virtual void foo() { std::cout << "base::foo()\n"; }
virtual void bar() = 0;
virtual ~A() {}
};
class B : public A {
int y;
public:
virtual void bar() { std::cout << "Derived::bar()"; }
virtual void baz() { std::cout << "Added function"; }
};
int main() {
A a;
B b;
}
This is going to result in a layout something on this general order:
So, each object contains its own copy of the object's data, which is an amalgamation of all the data defined in that class and all its base classes. When it contains at least one virtual function, it has a vtable pointer. That points to a table somewhere in the generated code. That table, in turn, contains pointers to the virtual functions for the class. The key to this working is that (for virtual functions that are common between them) the base class and derived class store those pointers at the same offsets in the vtable. When you invoke a virtual function, the compiler generates code to "chase" the vtable pointer, then invoke the function at the right offset in the vtable.
Although it's not shown directly here, when each member function (virtual or otherwise) is called, the address of the variable is typically passed as a hidden parameter that's named this inside the function. References to members can use this implicitly (so an assignment like somember=a; is really equivalent to this->somemember = a;).
Note: this is depicting how things are typically done--at least in theory, an implementation is free to do things entirely differently, as long as what it does meets the requirements in the standard. That said, every implementation of which I'm aware works fairly similarly.
Note: This question is purely about asm.js not about C++ nor any other programming language.
As the title already says:
How should a function pointer be implemented in a efficient way?
I couldn't find anything on the web, so I figured asking it here.
Edit:
I would like to implement virtual functions in the compiler I'm working on.
In C++ I would do something like this to generate a vtable:
#include <iostream>
class Base {
public:
virtual void doSomething() = 0;
};
class Derived : public Base {
public:
void doSomething() {
std::cout << "I'm doing something..." << std::endl;
}
};
int main()
{
Base* instance = new Derived();
instance->doSomething();
return 0;
}
To be more precise; how can I generate a vtable in asm.js without the need of plain JavaScript?
In any case, I would like the "near native" capabilities of asm.js while using function pointers.
The solution may be suitable for computer generated code only.
Looking over how asm.js works, I believe your best bet would be to use the method the original CFront compiler used: compile the virtual methods down to functions that take a this pointer, and use thunks to correct the this pointer before passing it. I'll go through it step by step:
No Inheritance
Reduce methods to special functions:
void ExampleObject::foo( void );
would be transformed into
void exampleobject_foo( ExampleObject* this );
This works fine for non-inheritance based objects.
Single Inheritance
We can easily add support for arbitrary large amount of single inheritance through a simple trick: always store the object in memory base first:
class A : public B
would become, in memory:
[[ B ] A ]
Getting closer!
Multiple Inheritance
Now, multiple inheritance makes this much harder to work with
class A : public B, public C
It's impossible for both B and C to be at the start of A; they simply cannot co-exist. There are two choices:
Store an explicit offset (known as delta) for each call to base.
Do not allow calls through A to B or C
The second choice is much preferable for a variety of reasons; if you are calling a base class member function, it's rare you would want to do it through a derived class. Instead, you could simply go C::conlyfunc, which could then do the adjustment to your pointer for you at no cost. Allowing A::conlyfunc removes important information that the compiler could have used, at very little benefit.
The first choice is used in C++; all multiple inheritance objects call a thunk before each call to a base class, which adjusts the this pointer to point to the subobject inside it. In a simple example:
class ExampleBaseClass
{
void foo( void );
}
class ExampleDerivedClass : public ExampleBaseClass, private IrrelevantBaseClass
{
void bar( void );
}
would then become
void examplebaseclass_foo( ExampleBaseClass* this );
void examplederivedclass_bar( ExampleDerivedClass* this);
void examplederivedclass_thunk_foo( ExampleDerivedClass* this)
{
examplebaseclass_foo( this + delta );
}
This could be inlined in many situations, so it's not too big of overhead. However, if you could never refer to ExampleBaseClass::foo as ExampleDerivedClass::foo, these thunks wouldn't be needed, as the delta would be easily discernible from the call itself.
Virtual functions
Virtual functions adds a whole new layer of complexity. In the multiple inheritance example, the thunks had fixed addresses to call; we were just adjusting the this before passing it to an already known function. With virtual functions, the function we're calling is unknown; we could be overridden by a derived object we have no possibility of knowing about at compile time, due to it being in another translation unit or a library, etc.
This means we need some form of dynamic dispatch for each object that has a virtually overridable function; many methods are possible, but C++ implementations tend to use a simple array of function pointers, or a vtable. To each object that has virtual functions, we add a point to an array as a hidden member, usually at the front:
class A
{
hidden:
void* vtable;
public:
virtual void foo( void );
}
We add thunk functions which redirect to the vtable
void a_foo( A* this )
{
int vindex = 0;
this->vtable[vindex](this);
}
The vtable is then populated with pointers to the functions we actually want to call:
vtable[0] = &A::foo_default; // our baseclass implimentation of foo
In a derived class, if we wish to override this virtual function, all we need to do is change the vtable in our own object, to point to the new function, and it will override in the base class as well:
class B: public A
{
virtual void foo( void );
}
will then do this in the constructor:
((A*)this)->vtable[0] = &B::foo;
Finally, we have support for all forms of inheritance!
Almost.
Virtual Inheritance
There is one final caveat with this implementation: if you continue to allow Derived::foo to be used when what you really mean is Base::foo, you get the diamond problem:
class A : public B, public C;
class B : public D;
class C : public D;
A::DFunc(); // Which D?
This problem can also occur when you use base classes as stateful classes, or when you put function that should be has-a rather than is-a; generally, it's a sign of a need for a restructure. But not always.
In C++, this has a solution that is not very elegant, but works:
class A : public B, public C;
class B : virtual D;
class C : virtual D;
This requires those who implement such classes and hierarchies to think ahead and intentionally make their classes a little slower, to support a possible future usage. But it does solve the problem.
How can we implement this solution?
[ [ D ] [ B ] [ Dptr ] [ C ] [ Dptr ] A ]
Rather than use the base class directly, as in normal inheritance, with virtual inheritance we push all usages of D through a pointer, adding an indirection, while stomping the multiple instantiations into a single one. Notice that both B and C have their own pointer, that both point to the same D; this is because B and C don't know if they are free floating copies or bound in derived objects. The same calls need to be used for both, or virtual functions won't work as expected.
Summary
Transform method calls into function calls with a special this parameter in base classes
Structure objects in memory so single inheritance is no different from no inheritance
Add thunks to adjust this pointers then call base classes for multiple inheritance
Add vtables to classes with virtual methods, and make all calls to methods go through vtable to method (thunk -> vtable -> method)
Deal with virtual inheritance through a pointer-to-baseobject rather than derive object calls
All of this is straightforward in js.asm.
Tim,
I'm by no means an asm.js expert but your question intrigues me. It goes to the hart of object oriented language design. It also seems ironic that you are recreating machine-level problems in the javascript domain.
The solution to your question it seems to me is that you will need to setup an accounting of defined types and functions. In Java this is typically done by decorating bytecode with identifiers that represent the correct class->function mapping of any given object. If you use a Int32 identifier for each class that is defined and an additionaly Int32 identifier for each function defined you can then store these in the object representations on the heap. Your vtable is then no more than the mapping of these combination to specific functions.
I hope this helps you.
I am not very familiar with the exact syntax of asm.js, but here is how I implemented a vtable in a compiler of mine (for x86):
Each object are derived from a struct like this:
struct Object {
VTable *vtable;
};
Then the other types I use will look something like this in c++-syntax:
struct MyInt : Vtable {
int value;
};
which is (in this case) equivalent to:
struct MyInt {
VTable *vtable;
int value;
};
So the final layout of the objects are that at offset 0, I know I have a pointer to a vtable. The vtable I use is simply an array of function pointers, again in C-syntax the type VTable could be defined as follows:
typedef Function *VTable;
Where in C i would use void * instead of Function *, since the actual types of the function will vary. What is left for the compiler to do is:
1: For each type containing virtual functions, create a global vtable and populate it with function pointers to the overridden functions.
2: When an object is created, set the vtable member of the object (at offset 0) to point to the global vtable.
Then when you want to call virtual functions you can do something like this:
(*myObject->vtable[1])(1);
to call the function your compiler has assigned the ID 1 in the vtable (methodB in the example below).
A final example: Let's say we have the following two classes:
class A {
public:
virtual int methodA(int) { ... }
virtual int methodB(int) { ... }
virtual int methodC(int) { ... }
};
class B : public A {
public:
virtual int methodA(int) { ... }
virtual int methodB(int) { ... }
};
The VTable for class A and B can look like this:
A: B:
0: &A::methodA 0: &B::methodA
1: &A::methodB 1: &B::methodB
2: &A::methodC 2: &A::methodC
By using this logic, we know that when we are calling methodB on any type derived from A, we shall call whatever function is located at index 1 in the vtable of that object.
Of course, this solution do not work right away if you want to allow for multiple inheritance, but I am fairly sure it can be extended to do so. After some debugging with Visual Studio 2008, it seems like this is more or less how the vtables are implemented there (of course there it is extended to handle multiple inheritance, I have not tried to figure that out yet).
I hope you get some ideas that can be applied in asm.js at least. Like I said, I do not know exactly how asm.js works, but I have managed to implement this system in x86 assembly and I do not see any issues with implementing it in JavaScript either, so I hope it can be used in asm.js as well.
Consider the following C++ code:
class A
{
public:
virtual void f()=0;
};
int main()
{
void (A::*f)()=&A::f;
}
If I'd have to guess, I'd say that &A::f in this context would mean "the address of A's implementation of f()", since there is no explicit seperation between pointers to regular member functions and virtual member functions. And since A doesn't implement f(), that would be a compile error. However, it isn't.
And not only that. The following code:
void (A::*f)()=&A::f;
A *a=new B; // B is a subclass of A, which implements f()
(a->*f)();
will actually call B::f.
How does it happen?
It works because the Standard says that's how it should happen. I did some tests with GCC, and it turns out for virtual functions, GCC stores the virtual table offset of the function in question, in bytes.
struct A { virtual void f() { } virtual void g() { } };
int main() {
union insp {
void (A::*pf)();
ptrdiff_t pd[2];
};
insp p[] = { { &A::f }, { &A::g } };
std::cout << p[0].pd[0] << " "
<< p[1].pd[0] << std::endl;
}
That program outputs 1 5 - the byte offsets of the virtual table entries of those two functions. It follows the Itanium C++ ABI, which specifies that.
Here is way too much information about member function pointers. There's some stuff about virtual functions under "The Well-Behaved Compilers", although IIRC when I read the article I was skimming that part, since the article is actually about implementing delegates in C++.
http://www.codeproject.com/KB/cpp/FastDelegate.aspx
The short answer is that it depends on the compiler, but one possibility is that the member function pointer is implemented as a struct containing a pointer to a "thunk" function which makes the virtual call.
I'm not entirely certain, but I think it's just regular polymorphic behavior. I think that &A::f actually means the address of the function pointer in the class's vtable, and that's why you aren't getting a compiler error. The space in the vtable is still allocated, and that is the location you are actually getting back.
This makes sense because derived classes essentially overwrite these values with pointers to their functions. This is why (a->*f)() works in your second example - f is referencing the vtable that is implemented in the derived class.
We all know what virtual functions are in C++, but how are they implemented at a deep level?
Can the vtable be modified or even directly accessed at runtime?
Does the vtable exist for all classes, or only those that have at least one virtual function?
Do abstract classes simply have a NULL for the function pointer of at least one entry?
Does having a single virtual function slow down the whole class? Or only the call to the function that is virtual? And does the speed get affected if the virtual function is actually overwritten or not, or does this have no effect so long as it is virtual.
How are virtual functions implemented at a deep level?
From "Virtual Functions in C++":
Whenever a program has a virtual function declared, a v - table is constructed for the class. The v-table consists of addresses to the virtual functions for classes that contain one or more virtual functions. The object of the class containing the virtual function contains a virtual pointer that points to the base address of the virtual table in memory. Whenever there is a virtual function call, the v-table is used to resolve to the function address. An object of the class that contains one or more virtual functions contains a virtual pointer called the vptr at the very beginning of the object in the memory. Hence the size of the object in this case increases by the size of the pointer. This vptr contains the base address of the virtual table in memory. Note that virtual tables are class specific, i.e., there is only one virtual table for a class irrespective of the number of virtual functions it contains. This virtual table in turn contains the base addresses of one or more virtual functions of the class. At the time when a virtual function is called on an object, the vptr of that object provides the base address of the virtual table for that class in memory. This table is used to resolve the function call as it contains the addresses of all the virtual functions of that class. This is how dynamic binding is resolved during a virtual function call.
Can the vtable be modified or even directly accessed at runtime?
Universally, I believe the answer is "no". You could do some memory mangling to find the vtable but you still wouldn't know what the function signature looks like to call it. Anything that you would want to achieve with this ability (that the language supports) should be possible without access to the vtable directly or modifying it at runtime. Also note, the C++ language spec does not specify that vtables are required - however that is how most compilers implement virtual functions.
Does the vtable exist for all objects, or only those that have at least one virtual function?
I believe the answer here is "it depends on the implementation" since the spec doesn't require vtables in the first place. However, in practice, I believe all modern compilers only create a vtable if a class has at least 1 virtual function. There is a space overhead associated with the vtable and a time overhead associated with calling a virtual function vs a non-virtual function.
Do abstract classes simply have a NULL for the function pointer of at least one entry?
The answer is it is unspecified by the language spec so it depends on the implementation. Calling the pure virtual function results in undefined behavior if it is not defined (which it usually isn't) (ISO/IEC 14882:2003 10.4-2). In practice it does allocate a slot in the vtable for the function but does not assign an address to it. This leaves the vtable incomplete which requires the derived classes to implement the function and complete the vtable. Some implementations do simply place a NULL pointer in the vtable entry; other implementations place a pointer to a dummy method that does something similar to an assertion.
Note that an abstract class can define an implementation for a pure virtual function, but that function can only be called with a qualified-id syntax (ie., fully specifying the class in the method name, similar to calling a base class method from a derived class). This is done to provide an easy to use default implementation, while still requiring that a derived class provide an override.
Does having a single virtual function slow down the whole class or only the call to the function that is virtual?
This is getting to the edge of my knowledge, so someone please help me out here if I'm wrong!
I believe that only the functions that are virtual in the class experience the time performance hit related to calling a virtual function vs. a non-virtual function. The space overhead for the class is there either way. Note that if there is a vtable, there is only 1 per class, not one per object.
Does the speed get affected if the virtual function is actually overridden or not, or does this have no effect so long as it is virtual?
I don't believe the execution time of a virtual function that is overridden decreases compared to calling the base virtual function. However, there is an additional space overhead for the class associated with defining another vtable for the derived class vs the base class.
Additional Resources:
http://www.codersource.net/published/view/325/virtual_functions_in.aspx (via way back machine)
http://en.wikipedia.org/wiki/Virtual_table
http://www.codesourcery.com/public/cxx-abi/abi.html#vtable
Can the vtable be modified or even directly accessed at runtime?
Not portably, but if you don't mind dirty tricks, sure!
WARNING: This technique is not recommended for use by children, adults under the age of 969, or small furry creatures from Alpha Centauri. Side effects may include demons which fly out of your nose, the abrupt appearence of Yog-Sothoth as a required approver on all subsequent code reviews, or the retroactive addition of IHuman::PlayPiano() to all existing instances]
In most compilers I've seen, the vtbl * is the first 4 bytes of the object, and the vtbl contents are simply an array of member pointers there (generally in the order they were declared, with the base class's first). There are of course other possible layouts, but that's what I've generally observed.
class A {
public:
virtual int f1() = 0;
};
class B : public A {
public:
virtual int f1() { return 1; }
virtual int f2() { return 2; }
};
class C : public A {
public:
virtual int f1() { return -1; }
virtual int f2() { return -2; }
};
A *x = new B;
A *y = new C;
A *z = new C;
Now to pull some shenanigans...
Changing class at runtime:
std::swap(*(void **)x, *(void **)y);
// Now x is a C, and y is a B! Hope they used the same layout of members!
Replacing a method for all instances (monkeypatching a class)
This one's a little trickier, since the vtbl itself is probably in read-only memory.
int f3(A*) { return 0; }
mprotect(*(void **)x,8,PROT_READ|PROT_WRITE|PROT_EXEC);
// Or VirtualProtect on win32; this part's very OS-specific
(*(int (***)(A *)x)[0] = f3;
// Now C::f1() returns 0 (remember we made x into a C above)
// so x->f1() and z->f1() both return 0
The latter is rather likely to make virus-checkers and the link wake up and take notice, due to the mprotect manipulations. In a process using the NX bit it may well fail.
Does having a single virtual function slow down the whole class?
Or only the call to the function that is virtual? And does the speed get affected if the virtual function is actually overwritten or not, or does this have no effect so long as it is virtual.
Having virtual functions slows down the whole class insofar as one more item of data has to be initialized, copied, … when dealing with an object of such a class. For a class with half a dozen members or so, the difference should be neglible. For a class which just contains a single char member, or no members at all, the difference might be notable.
Apart from that, it is important to note that not every call to a virtual function is a virtual function call. If you have an object of a known type, the compiler can emit code for a normal function invocation, and can even inline said function if it feels like it. It's only when you do polymorphic calls, via a pointer or reference which might point at an object of the base class or at an object of some derived class, that you need the vtable indirection and pay for it in terms of performance.
struct Foo { virtual ~Foo(); virtual int a() { return 1; } };
struct Bar: public Foo { int a() { return 2; } };
void f(Foo& arg) {
Foo x; x.a(); // non-virtual: always calls Foo::a()
Bar y; y.a(); // non-virtual: always calls Bar::a()
arg.a(); // virtual: must dispatch via vtable
Foo z = arg; // copy constructor Foo::Foo(const Foo&) will convert to Foo
z.a(); // non-virtual Foo::a, since z is a Foo, even if arg was not
}
The steps the hardware has to take are essentially the same, no matter whether the function is overwritten or not. The address of the vtable is read from the object, the function pointer retrieved from the appropriate slot, and the function called by pointer. In terms of actual performance, branch predictions might have some impact. So for example, if most of your objects refer to the same implementation of a given virtual function, then there is some chance that the branch predictor will correctly predict which function to call even before the pointer has been retrieved. But it doesn't matter which function is the common one: it could be most objects delegating to the non-overwritten base case, or most objects belonging to the same subclass and therefore delegating to the same overwritten case.
how are they implemented at a deep level?
I like the idea of jheriko to demonstrate this using a mock implementation. But I'd use C to implement something akin to the code above, so that the low level is more easily seen.
parent class Foo
typedef struct Foo_t Foo; // forward declaration
struct slotsFoo { // list all virtual functions of Foo
const void *parentVtable; // (single) inheritance
void (*destructor)(Foo*); // virtual destructor Foo::~Foo
int (*a)(Foo*); // virtual function Foo::a
};
struct Foo_t { // class Foo
const struct slotsFoo* vtable; // each instance points to vtable
};
void destructFoo(Foo* self) { } // Foo::~Foo
int aFoo(Foo* self) { return 1; } // Foo::a()
const struct slotsFoo vtableFoo = { // only one constant table
0, // no parent class
destructFoo,
aFoo
};
void constructFoo(Foo* self) { // Foo::Foo()
self->vtable = &vtableFoo; // object points to class vtable
}
void copyConstructFoo(Foo* self,
Foo* other) { // Foo::Foo(const Foo&)
self->vtable = &vtableFoo; // don't copy from other!
}
derived class Bar
typedef struct Bar_t { // class Bar
Foo base; // inherit all members of Foo
} Bar;
void destructBar(Bar* self) { } // Bar::~Bar
int aBar(Bar* self) { return 2; } // Bar::a()
const struct slotsFoo vtableBar = { // one more constant table
&vtableFoo, // can dynamic_cast to Foo
(void(*)(Foo*)) destructBar, // must cast type to avoid errors
(int(*)(Foo*)) aBar
};
void constructBar(Bar* self) { // Bar::Bar()
self->base.vtable = &vtableBar; // point to Bar vtable
}
function f performing virtual function call
void f(Foo* arg) { // same functionality as above
Foo x; constructFoo(&x); aFoo(&x);
Bar y; constructBar(&y); aBar(&y);
arg->vtable->a(arg); // virtual function call
Foo z; copyConstructFoo(&z, arg);
aFoo(&z);
destructFoo(&z);
destructBar(&y);
destructFoo(&x);
}
So you can see, a vtable is just a static block in memory, mostly containing function pointers. Every object of a polymorphic class will point to the vtable corresponding to its dynamic type. This also makes the connection between RTTI and virtual functions clearer: you can check what type a class is simply by looking at what vtable it points at. The above is simplified in many ways, like e.g. multiple inheritance, but the general concept is sound.
If arg is of type Foo* and you take arg->vtable, but is actually an object of type Bar, then you still get the correct address of the vtable. That's because the vtable is always the first element at the address of the object, no matter whether it's called vtable or base.vtable in a correctly-typed expression.
Usually with a VTable, an array of pointers to functions.
Here is a runnable manual implementation of virtual table in modern C++. It has well-defined semantics, no hacks and no void*.
Note: .* and ->* are different operators than * and ->. Member function pointers work differently.
#include <iostream>
#include <vector>
#include <memory>
struct vtable; // forward declare, we need just name
class animal
{
public:
const std::string& get_name() const { return name; }
// these will be abstract
bool has_tail() const;
bool has_wings() const;
void sound() const;
protected: // we do not want animals to be created directly
animal(const vtable* vtable_ptr, std::string name)
: vtable_ptr(vtable_ptr), name(std::move(name)) { }
private:
friend vtable; // just in case for non-public methods
const vtable* const vtable_ptr;
std::string name;
};
class cat : public animal
{
public:
cat(std::string name);
// functions to bind dynamically
bool has_tail() const { return true; }
bool has_wings() const { return false; }
void sound() const
{
std::cout << get_name() << " does meow\n";
}
};
class dog : public animal
{
public:
dog(std::string name);
// functions to bind dynamically
bool has_tail() const { return true; }
bool has_wings() const { return false; }
void sound() const
{
std::cout << get_name() << " does whoof\n";
}
};
class parrot : public animal
{
public:
parrot(std::string name);
// functions to bind dynamically
bool has_tail() const { return false; }
bool has_wings() const { return true; }
void sound() const
{
std::cout << get_name() << " does crrra\n";
}
};
// now the magic - pointers to member functions!
struct vtable
{
bool (animal::* const has_tail)() const;
bool (animal::* const has_wings)() const;
void (animal::* const sound)() const;
// constructor
vtable (
bool (animal::* const has_tail)() const,
bool (animal::* const has_wings)() const,
void (animal::* const sound)() const
) : has_tail(has_tail), has_wings(has_wings), sound(sound) { }
};
// global vtable objects
const vtable vtable_cat(
static_cast<bool (animal::*)() const>(&cat::has_tail),
static_cast<bool (animal::*)() const>(&cat::has_wings),
static_cast<void (animal::*)() const>(&cat::sound));
const vtable vtable_dog(
static_cast<bool (animal::*)() const>(&dog::has_tail),
static_cast<bool (animal::*)() const>(&dog::has_wings),
static_cast<void (animal::*)() const>(&dog::sound));
const vtable vtable_parrot(
static_cast<bool (animal::*)() const>(&parrot::has_tail),
static_cast<bool (animal::*)() const>(&parrot::has_wings),
static_cast<void (animal::*)() const>(&parrot::sound));
// set vtable pointers in constructors
cat::cat(std::string name) : animal(&vtable_cat, std::move(name)) { }
dog::dog(std::string name) : animal(&vtable_dog, std::move(name)) { }
parrot::parrot(std::string name) : animal(&vtable_parrot, std::move(name)) { }
// implement dynamic dispatch
bool animal::has_tail() const
{
return (this->*(vtable_ptr->has_tail))();
}
bool animal::has_wings() const
{
return (this->*(vtable_ptr->has_wings))();
}
void animal::sound() const
{
(this->*(vtable_ptr->sound))();
}
int main()
{
std::vector<std::unique_ptr<animal>> animals;
animals.push_back(std::make_unique<cat>("grumpy"));
animals.push_back(std::make_unique<cat>("nyan"));
animals.push_back(std::make_unique<dog>("doge"));
animals.push_back(std::make_unique<parrot>("party"));
for (const auto& a : animals)
a->sound();
// note: destructors are not dispatched virtually
}
This answer has been incorporated into the Community Wiki answer
Do abstract classes simply have a NULL for the function pointer of at least one entry?
The answer for that is that it is unspecified - calling the pure virtual function results in undefined behavior if it is not defined (which it usually isn't) (ISO/IEC 14882:2003 10.4-2). Some implementations do simply place a NULL pointer in the vtable entry; other implementations place a pointer to a dummy method that does something similar to an assertion.
Note that an abstract class can define an implementation for a pure virtual function, but that function can only be called with a qualified-id syntax (ie., fully specifying the class in the method name, similar to calling a base class method from a derived class). This is done to provide an easy to use default implementation, while still requiring that a derived class provide an override.
You can recreate the functionality of virtual functions in C++ using function pointers as members of a class and static functions as the implementations, or using pointer to member functions and member functions for the implementations. There are only notational advantages between the two methods... in fact virtual function calls are just a notational convenience themselves. In fact inheritance is just a notational convenience... it can all be implemented without using the language features for inheritance. :)
The below is crap untested, probably buggy code, but hopefully demonstrates the idea.
e.g.
class Foo
{
protected:
void(*)(Foo*) MyFunc;
public:
Foo() { MyFunc = 0; }
void ReplciatedVirtualFunctionCall()
{
MyFunc(*this);
}
...
};
class Bar : public Foo
{
private:
static void impl1(Foo* f)
{
...
}
public:
Bar() { MyFunc = impl1; }
...
};
class Baz : public Foo
{
private:
static void impl2(Foo* f)
{
...
}
public:
Baz() { MyFunc = impl2; }
...
};
I'll try to make it simple :)
We all know what virtual functions are in C++, but how are they implemented at a deep level?
This is an array with pointers to functions, which are implementations of a particular virtual function. An index in this array represents particular index of a virtual function defined for a class. This includes pure virtual functions.
When a polymorphic class derives from another polymorphic class, we may have the following situations:
The deriving class does not add new virtual functions nor overrides any. In this case this class shares the vtable with the base class.
The deriving class adds and overrides virtual methods. In this case it gets its own vtable, where the added virtual functions have index starting past the last derived one.
Multiple polymorphic classes in the inheritance. In this case we have an index-shift between second and next bases and the index of it in the derived class
Can the vtable be modified or even directly accessed at runtime?
Not standard way - there's no API to access them. Compilers may have some extensions or private APIs to access them, but that may be only an extension.
Does the vtable exist for all classes, or only those that have at least one virtual function?
Only those that have at least one virtual function (be it even destructor) or derive at least one class that has its vtable ("is polymorphic").
Do abstract classes simply have a NULL for the function pointer of at least one entry?
That's a possible implementation, but rather not practiced. Instead there is usually a function that prints something like "pure virtual function called" and does abort(). The call to that may occur if you try to call the abstract method in the constructor or destructor.
Does having a single virtual function slow down the whole class? Or only the call to the function that is virtual? And does the speed get affected if the virtual function is actually overwritten or not, or does this have no effect so long as it is virtual.
The slowdown is only dependent on whether the call is resolved as direct call or as a virtual call. And nothing else matters. :)
If you call a virtual function through a pointer or reference to an object, then it will be always implemented as virtual call - because the compiler can never know what kind of object will be assigned to this pointer in runtime, and whether it is of a class in which this method is overridden or not. Only in two cases the compiler can resolve the call to a virtual function as a direct call:
If you call the method through a value (a variable or result of a function that returns a value) - in this case the compiler has no doubts what the actual class of the object is, and can "hard-resolve" it at compile time.
If the virtual method is declared final in the class to which you have a pointer or reference through which you call it (only in C++11). In this case compiler knows that this method cannot undergo any further overriding and it can only be the method from this class.
Note though that virtual calls have only overhead of dereferencing two pointers. Using RTTI (although only available for polymorphic classes) is slower than calling virtual methods, should you find a case to implement the same thing two such ways. For example, defining virtual bool HasHoof() { return false; } and then override only as bool Horse::HasHoof() { return true; } would provide you with ability to call if (anim->HasHoof()) that will be faster than trying if(dynamic_cast<Horse*>(anim)). This is because dynamic_cast has to walk through the class hierarchy in some cases even recursively to see if there can be built the path from the actual pointer type and the desired class type. While the virtual call is always the same - dereferencing two pointers.
Each object has a vtable pointer that points to an array of member functions.
Something not mentioned here in all these answers is that in case of multiple inheritance, where the base classes all have virtual methods. The inheriting class has multiple pointers to a vmt.
The result is that the size of each instance of such an object is bigger.
Everybody knows that a class with virtual methods has 4 bytes extra for the vmt, but in case of multiple inheritance it is for each base class that has virtual methods times 4. 4 being the size of the pointer.
Burly's answers are correct here except for the question:
Do abstract classes simply have a NULL for the function pointer of at least one entry?
The answer is that no virtual table is created at all for abstract classes. There is no need since no objects of these classes can be created!
In other words if we have:
class B { ~B() = 0; }; // Abstract Base class
class D : public B { ~D() {} }; // Concrete Derived class
D* pD = new D();
B* pB = pD;
The vtbl pointer accessed through pB will be the vtbl of class D. This is exactly how polymorphism is implemented. That is, how D methods are accessed through pB. There is no need for a vtbl for class B.
In response to Mike's comment below...
If the B class in my description has a virtual method foo() that is not overridden by D and a virtual method bar() that is overridden, then D's vtbl will have a pointer to B's foo() and to its own bar(). There is still no vtbl created for B.
very cute proof of concept i made a bit earlier(to see if order of inheritence matters); let me know if your implementation of C++ actually rejects it(my version of gcc only gives a warning for assigning anonymous structs, but that's a bug), i'm curious.
CCPolite.h:
#ifndef CCPOLITE_H
#define CCPOLITE_H
/* the vtable or interface */
typedef struct {
void (*Greet)(void *);
void (*Thank)(void *);
} ICCPolite;
/**
* the actual "object" literal as C++ sees it; public variables be here too
* all CPolite objects use(are instances of) this struct's structure.
*/
typedef struct {
ICCPolite *vtbl;
} CPolite;
#endif /* CCPOLITE_H */
CCPolite_constructor.h:
/**
* unconventionally include me after defining OBJECT_NAME to automate
* static(allocation-less) construction.
*
* note: I assume CPOLITE_H is included; since if I use anonymous structs
* for each object, they become incompatible and cause compile time errors
* when trying to do stuff like assign, or pass functions.
* this is similar to how you can't pass void * to windows functions that
* take handles; these handles use anonymous structs to make
* HWND/HANDLE/HINSTANCE/void*/etc not automatically convertible, and
* require a cast.
*/
#ifndef OBJECT_NAME
#error CCPolite> constructor requires object name.
#endif
CPolite OBJECT_NAME = {
&CCPolite_Vtbl
};
/* ensure no global scope pollution */
#undef OBJECT_NAME
main.c:
#include <stdio.h>
#include "CCPolite.h"
// | A Greeter is capable of greeting; nothing else.
struct IGreeter
{
virtual void Greet() = 0;
};
// | A Thanker is capable of thanking; nothing else.
struct IThanker
{
virtual void Thank() = 0;
};
// | A Polite is something that implements both IGreeter and IThanker
// | Note that order of implementation DOES MATTER.
struct IPolite1 : public IGreeter, public IThanker{};
struct IPolite2 : public IThanker, public IGreeter{};
// | implementation if IPolite1; implements IGreeter BEFORE IThanker
struct CPolite1 : public IPolite1
{
void Greet()
{
puts("hello!");
}
void Thank()
{
puts("thank you!");
}
};
// | implementation if IPolite1; implements IThanker BEFORE IGreeter
struct CPolite2 : public IPolite2
{
void Greet()
{
puts("hi!");
}
void Thank()
{
puts("ty!");
}
};
// | imposter Polite's Greet implementation.
static void CCPolite_Greet(void *)
{
puts("HI I AM C!!!!");
}
// | imposter Polite's Thank implementation.
static void CCPolite_Thank(void *)
{
puts("THANK YOU, I AM C!!");
}
// | vtable of the imposter Polite.
ICCPolite CCPolite_Vtbl = {
CCPolite_Thank,
CCPolite_Greet
};
CPolite CCPoliteObj = {
&CCPolite_Vtbl
};
int main(int argc, char **argv)
{
puts("\npart 1");
CPolite1 o1;
o1.Greet();
o1.Thank();
puts("\npart 2");
CPolite2 o2;
o2.Greet();
o2.Thank();
puts("\npart 3");
CPolite1 *not1 = (CPolite1 *)&o2;
CPolite2 *not2 = (CPolite2 *)&o1;
not1->Greet();
not1->Thank();
not2->Greet();
not2->Thank();
puts("\npart 4");
CPolite1 *fake = (CPolite1 *)&CCPoliteObj;
fake->Thank();
fake->Greet();
puts("\npart 5");
CPolite2 *fake2 = (CPolite2 *)fake;
fake2->Thank();
fake2->Greet();
puts("\npart 6");
#define OBJECT_NAME fake3
#include "CCPolite_constructor.h"
fake = (CPolite1 *)&fake3;
fake->Thank();
fake->Greet();
puts("\npart 7");
#define OBJECT_NAME fake4
#include "CCPolite_constructor.h"
fake2 = (CPolite2 *)&fake4;
fake2->Thank();
fake2->Greet();
return 0;
}
output:
part 1
hello!
thank you!
part 2
hi!
ty!
part 3
ty!
hi!
thank you!
hello!
part 4
HI I AM C!!!!
THANK YOU, I AM C!!
part 5
THANK YOU, I AM C!!
HI I AM C!!!!
part 6
HI I AM C!!!!
THANK YOU, I AM C!!
part 7
THANK YOU, I AM C!!
HI I AM C!!!!
note since I am never allocating my fake object, there is no need to do any destruction; destructors are automatically put at the end of scope of dynamically allocated objects to reclaim the memory of the object literal itself and the vtable pointer.