When is a vtable created in C ++?

When exactly does the compiler create a table of virtual functions?

1) when the class contains at least one virtual function.

OR

2) when the immediate base class contains at least one virtual function.

OR

3) if any parent class at any level of the hierarchy contains at least one virtual function.

A related question: Is it possible to refuse dynamic sending in the C ++ hierarchy?

eg. consider the following example.

#include <iostream> using namespace std; class A { public: virtual void f(); }; class B: public A { public: void f(); }; class C: public B { public: void f(); }; 

What classes will contain a V-table?

Since B does not declare f () as virtual, does the class C receive dynamic polymorphism?

+22
c ++ polymorphism virtual-functions vtable
Dec 26 '09 at 18:02
source share
6 answers

Beyond "vtables are implementation specific" (which they are) if vtable is used: there will be unique vtables for each of your classes. Despite the fact that B :: f and C :: f are not declared virtual, because there is a mapping of the signature of the virtual method from the base class (A in your code), B :: f and C :: f are implicitly virtual, since each the class has at least one unique virtual method (B :: f overrides A :: f for instances of B and C :: f similarly for instances of C), you need three vtables.

You should not worry about such details at all. It is important to have virtual dispatch or not. You do not need to use virtual send, explicitly indicating which function to call, but this is usually only useful when implementing a virtual method (for example, to call the base method). Example:

 struct B { virtual void f() {} virtual void g() {} }; struct D : B { virtual void f() { // would be implicitly virtual even if not declared virtual B::f(); // do D-specific stuff } virtual void g() {} }; int main() { { B b; bg(); bB::g(); // both call B::g } { D d; B& b = d; bg(); // calls D::g bB::g(); // calls B::g bD::g(); // not allowed dD::g(); // calls D::g void (B::*p)() = &B::g; (b.*p)(); // calls D::g // calls through a function pointer always use virtual dispatch // (if the pointed-to function is virtual) } return 0; } 

Some specific rules that may help; but don't quote me on them, I probably missed some cases:

  • If the class has virtual methods or virtual databases, even if they are inherited, then the instances must have a vtable pointer.
  • If a class declares non-inherited virtual methods (for example, when it does not have a base class), it must have its own vtable.
  • If a class has a different set of overriding methods than its first base class, then it must have its own vtable and cannot reuse the database. (Destructors usually require this.)
  • If a class has several base classes, the second or later base has virtual methods:
    • If none of the earlier bases has virtual methods, and empty base optimization is applied to all earlier bases, then consider this base as the first base class.
    • Otherwise, the class must have its own vtable.
  • If the class has virtual base classes, it must have its own vtable.

Remember that vtable is like a static member of a class data, and instances only have pointers to them.

Also see C ++ comprehensive article : Under the Hood (March 1994) Ian Gray. ( Try Google if this link dies.)

An example of reusing a vtable:

 struct B { virtual void f(); }; struct D : B { // does not override B::f // does not have other virtuals of its own void g(); // still might have its own non-virtuals int n; // and data members }; 

In particular, the B dtor notification is not virtual (and this is probably an error in the real code ), but in this example, the D instances point to the same vtable as in the B instances.

+22
Dec 26 '09 at 18:22
source share

Answer: "it depends." It depends on what you mean by โ€œcontain vtblโ€, and it depends on the decisions made by the developer of the particular compiler.

Strictly speaking, no 'class' never contains a table of virtual functions. Some instances of some classes contain pointers to virtual function tables. However, this is just one possible implementation of semantics.

In extreme cases, the compiler could hypothetically put a unique number in an instance indexed into the data structure used to select the corresponding instance of the virtual function.

If you ask: "What does GCC do?" or "What does Visual C ++ do?" then you can get a specific answer.

@ Hassan Side's answer is probably closer to what you asked, but itโ€™s very important to keep these concepts right here.

There is a behavior (dynamic dispatch based on which class was a newbie), and there is an implementation. Your question uses implementation terminology, although I suspect you were looking for a behavioral answer.

The behavioral answer is this: any class that declares or inherits a virtual function will exhibit dynamic behavior when calling this function. Any class that does not do this will not.

Implementation, the compiler allows you to do what this result wants to accomplish.

+8
Dec 26 '09 at 18:08
source share

Answer

A vtable is created when a class declaration contains a virtual function. A virtual table is introduced when the parent object โ€” anywhere in the hierarchy โ€” has a virtual function, allows you to call that parent Y. Any parent Y will not have a vtable (unless they have virtual for any other function in their hierarchical hierarchy )

Read on for discussion and tests.

- explanation -

When you specify a member function as virtual, there is a chance that you might try to use subclasses with the base class polymorphically at runtime. To support the C ++ language design performance guarantee, they proposed the easiest implementation strategy possible, that is, one level of indirection, and only when the class can be used polymorphically at runtime, and the programmer determines this by setting at least one virtual function.

You do not incur expenses on vtable if you avoid the virtual keyword.

- change: reflect your editing -

Only if the base class contains a virtual function, any other subclasses contain vtable. Parents of the specified base class do not have vtable.

In your example, all three classes will have vtable, because you can try using all three classes with A*.

- test - GCC 4+ -

 #include <iostream> class test_base { public: void x(){std::cout << "test_base" << "\n"; }; }; class test_sub : public test_base { public: virtual void x(){std::cout << "test_sub" << "\n"; } ; }; class test_subby : public test_sub { public: void x() { std::cout << "test_subby" << "\n"; } }; int main() { test_sub sub; test_base base; test_subby subby; test_sub * psub; test_base *pbase; test_subby * psubby; pbase = &sub; pbase->x(); psub = &subby; psub->x(); return 0; } 

Exit

 test_base test_subby 

test_base does not have a virtual table, so any click on it will use x() from test_base . test_sub , on the other hand, changes the character of x() , and its pointer will be indirect via vtable, and this will be shown by test_subby x() .

So vtable is only used in the hierarchy when the virtual keyword is used. Older ancestors do not have a vtable, and if a downgrade occurs, it will be associated with the functions of the ancestors.

+7
Dec 26 '09 at 18:11
source share

You have made every effort to make your question very clear and precise, but there is still a little information missing. You probably know that in implementations using V-Table, the table itself is usually an independent data structure stored outside polymorphic objects, while the objects themselves retain an implicit pointer to the table. So what are you asking about? May be:

  • When does an object get an implicit pointer to a V-table inserted into it?

or

  • When is a dedicated separate V-table created for a given type in a hierarchy?

The answer to the first question: an object receives an implicit pointer to a V-table inserted into it when the object is of the type of a polymorphic class. A class type is polymorphic if it contains at least one virtual function, or any of its direct or indirect parents is polymorphic (this is answer 3 from your set). Also note that in the case of multiple inheritance, an object can (and will) contain many V-Table pointers built into it.

The answer to the second question may be the same as for the first (option 3), with a possible exception. If a polymorphic class in the single inheritance hierarchy does not have its own virtual functions (no new virtual functions, no overrides for the parent virtual function), it is possible that the implementation may decide not to create a separate V-Table for this class, but instead use of this class is the immediate parent V-column (since it will be the same anyway). That is, in this case, both objects of the parent type and objects of the derived type will store the same value in their built-in V-Table pointers. This, of course, is highly implementation dependent. I tested GCC and MS VS 2005 and they do not work that way. They both create a separate V-table for the derived class in this situation, but I seem to recall a rumor about implementations that do not.

+3
Dec 26 '09 at 18:58
source share

C ++ standards do not allow the use of V-tables to create the illusion of polymorphic classes. In most cases, implementations use V-tables to store additional information. In short, these additional pieces of information are equipped when you have at least one virtual function.

+2
Dec 26 '09 at 18:15
source share

The behavior is defined in paragraph 2 of section 10.3 of the C ++ language specification:

If the virtual member function vf is declared in the class database and in the Derivatives class obtained directly or indirectly from the base, the member function vf with the same name and the same parameter list as Base :: vf is declared, then Derived :: vf is also virtual (regardless of whether it is so declared) and it overrides Base :: vf.

Designated the appropriate phrase. Thus, if your compiler creates v-tables in the usual sense, then all classes will have a v-table, since all their f () methods are virtual.

+1
Dec 26 '09 at 19:01
source share



All Articles