Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the compiler allowing this virtual function in a template class?

Tags:

c++

I know there are few threads about this topic. But what really confused me is the result I got is different from what everyone is saying.

Look this code below (compiled using GCC441):

#include <iostream>

using namespace std;

template<class T>
class A {
  public:
    A(T &t) : _a(t) {};
    virtual ~A() { cout << "Dtor-A" << endl;};
    virtual void print () { cout << "A: " << _a << endl; }
    T _a;
};

class B : public A<int> {
  public:
    B(int t) : A<int>(t) {}
    ~B() { cout << "Dtor-B" << endl;};
    void print() { cout << "B: " << endl; }
};

int main() {
  B b(2);

  A<int> *a = &b;
  a->print();

  A<int> *a2 = new B(4);
  a2->print();

  delete a2;
}

The result is:

B: 
B: 
Dtor-B
Dtor-A
Dtor-B
Dtor-A

If virtual function is not allowed in template class, why did I get this result?

like image 568
Orunner Avatar asked Mar 13 '12 12:03

Orunner


People also ask

Can a template class have virtual functions?

A class template can indeed contain virtual or pure virtual functions. This was employed by Andrei Alexandresu in "Modern C++ Design" to implement the visitor pattern using templates and type lists.

What is the role of compiler by templates?

Compiler creates a new instance of a template function for every data type. So compiler creates two functions in the above example, one for int and other for double. Every instance has its own copy of static variable. The int instance of function is called twice, so count is incremented for the second call.

How does the compiler implement virtual functions?

This is called “dynamic binding.” Most compilers use some variant of the following technique: if the object has one or more virtual functions, the compiler puts a hidden pointer in the object called a “virtual-pointer” or “v-pointer.” This v-pointer points to a global table called the “virtual-table” or “v-table.”

How does the compiler resolve a call to a virtual function?

A call to a virtual function is resolved according to the underlying type of object for which it is called. A call to a nonvirtual function is resolved according to the type of the pointer or reference.


1 Answers

You can't have a virtual function template in a class — this would be meaningless — but a virtual function in a class template is fine.

Once that class template Foo is instantiated, the resulting class Foo<T> has virtual functions that can be used as if they were part of any other type.

Let's examine the difference between the two:

Not OK

struct Foo {
   template <typename T>
   virtual void bar() {}      // Foo::bar<T> - prohibited, as marked "virtual"
};

// Impossible to resolve calls to Foo::bar<T>() at runtime, since
// such calls may require template instantiation, which may only occur
// at compile-time.

OK

template <typename T>
struct Foo {
   virtual void bar() {}      // Foo<T>::bar
};

// If Foo<T> is used in the program, then it will exist, in entirety.
// Foo<T>::bar() may thus be used as noraml.
like image 83
Lightness Races in Orbit Avatar answered Sep 29 '22 09:09

Lightness Races in Orbit