Templates and polymorphism

Dear All,

I am trying to use templates with polymorphism. I have written the following simple code, in which I instantiate 4 objects of the class component<T>, with different values of T, and I try to create a vector of pointers to these objects.

the code compiles, but it does not link. I get the following error, which is a bit non-sense for me:

abstract.cpp:(.text._ZN17AbstractComponentC2Ev[_ZN17AbstractComponentC5Ev]+0xf): undefined reference to `vtable for AbstractComponent'
/tmp/ccY4WjaC.o:(.rodata._ZTI9ComponentIdE[typeinfo for Component<double>]+0x10): undefined reference to `typeinfo for AbstractComponent'
/tmp/ccY4WjaC.o:(.rodata._ZTI9ComponentIcE[typeinfo for Component<char>]+0x10): undefined reference to `typeinfo for AbstractComponent'
/tmp/ccY4WjaC.o:(.rodata._ZTI9ComponentIiE[typeinfo for Component<int>]+0x10): undefined reference to `typeinfo for AbstractComponent'
collect2: ld returned 1 exit status

what does vtable mean?

This is the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  #include<iostream>
#include<vector>

class AbstractComponent
{
	public:
	virtual void display();
	//virtual AbstractComponent() {}
};

template<class T>
class Component : public AbstractComponent
{
	public:
	T v1;
	T v2;
	T v3;
	void display() {std::cout<<'(' << v1 <<", "<<v2<<", "<<v3<<")"<<std::endl;}
	Component(T v1_, T v2_, T v3_) : v1(v1_), v2(v2_), v3(v3_) {}
};

int main()
{
	Component<int> c1(3,4,4);
	Component<int> c2(4,5,6);
	Component<char> c3('x', 'y', 'z');
	Component<double> c4(3.3, 6.2, 4.7);
	
	std::vector<AbstractComponent*> V;
	V.push_back(&c1);
	V.push_back(&c2);
	V.push_back(&c3);
	V.push_back(&c4);
	
	for (int i=0; i<V.size(); i++)
		V[i]->display();
	
	return 0;
}
	

Thank you in advance for your kind help.
My best regards, Giuseppe
As my compiler helpfully says
ld: 0711-317 ERROR: Undefined symbol: Virtual table for class
 "AbstractComponent": Some possible causes are: first non-inline virtual 
function in "AbstractComponent" is not defined; or the class is a template 
instantiation and an explicit instantiation definition of the class is missing.


you can fix that by changing
virtual void display();
to
virtual void display() = 0;

And don't forget a virtual destructor, since you're currently leaking -- didn't notice the pointers weren't new'd.. still, do provide one

PS: templates have nothing to do with this, by the way.
Last edited on
Simply put, you declared but didn't define AbstractComponent::display(). You should make it a pure virtual, change line 7 to:
virtual void display() = 0;

To learn why, and more about the vtable check out
chapter 15: Polymorphism and Virtual Functions
in Bruce Eckel's aging but still excellent book
Thinking in C+ Vol1
available for free at
www.mindviewinc.com


Edited to add highlighting
Last edited on
Dear all,

I wish to thank you for the clear answers.
I do not understand how the virtual destructor should look like, since the AbstractComponent does not have members other than the member function void display.


Thanks again,
Panecasareccio
I do not understand how the virtual destructor should look like, since the AbstractComponent does not have members other than the member function void display.
virtual ~AbstractComponent() = default;
or, for older compilers,
virtual ~AbstractComponent() {}
Dear Cubbi,

I wish to thank you again for your help.

I have one more question, about performance. And memory usage.
Will a big array of pointers to AbstractComponent cause a larger usage of memory, with respect to an array of pointers to non-polymorphic objects, in order to store the specific type of each concrete object in the array?

Thanks again,
Panecasareccio
Array of pointers, no difference. You're just holding pointers.

Array of objects however, you get an extra vptr in each object for every class you inherit from.

Also a single vtable for each class that declares virtual functions. This of course would not be part of your array.

So if you inherit from one virtual base class, then the objects of your class will be bigger by the size of one pointer.

I think.
Topic archived. No new replies allowed.