C++ Undefined Reference to vtable and inheritance
Asked Answered
D

3

34

File A.h

#ifndef A_H_
#define A_H_

class A {
public:
    virtual ~A();
    virtual void doWork();
};

#endif

File Child.h

#ifndef CHILD_H_
#define CHILD_H_

#include "A.h"

class Child: public A {
private:
    int x,y;
public:
    Child();
    ~Child();
    void doWork();
};
#endif

And Child.cpp

#include "Child.h"

Child::Child(){
    x = 5;
}

Child::~Child(){...}

void Child::doWork(){...};

The compiler says that there is a undefined reference to vtable for A. I have tried lots of different things and yet none have worked.

My objective is for class A to be an Interface, and to seperate implementation code from headers.

Donelson answered 23/2, 2012 at 3:6 Comment(1)
You must define every non-pure virtual function that you declare. You don't need to define a non-virtual function that you declare but don't use.Diarmid
N
78

Why the error & how to resolve it?

You need to provide definitions for all virtual functions in class A. Only pure virtual functions are allowed to have no definitions.

i.e: In class A both the methods:

virtual ~A();
virtual void doWork();

should be defined(should have a body)

e.g.:

A.cpp

void A::doWork()
{
}
A::~A()
{
}

Caveat:
If you want your class A to act as an interface(a.k.a Abstract class in C++) then you should make the method pure virtual.

virtual void doWork() = 0;

Good Read:

What does it mean that the "virtual table" is an unresolved external?
When building C++, the linker says my constructors, destructors or virtual tables are undefined.

Nikitanikki answered 23/2, 2012 at 3:10 Comment(4)
@user1227351: Updated the answer to explain better.Read the links for further explanation.Nikitanikki
Having virtual ~A(); virtual void doWork() = 0; still gives vtable error =/. But without the destructor it works fine. However without it, if i do something like: A *a = new Child(); delete a; obviously it will not call Child::~Child(). Is there a workaround?Donelson
The solution is to place A::~A(){} in Child.cppDonelson
With C++11, you can use "default" keyword to let the compiler do the job. ex: virtual doSomething() = default;Moazami
P
6

My objective is for A to be an Interface, and to seperate implementation code from headers.

In that case, make the member function as pure virtual in class A.

class A {
  // ...
  virtual void doWork() = 0;
};
Privation answered 23/2, 2012 at 3:12 Comment(5)
That removes the error if I also remove the destructor. In that case if i do: A a = new Child(); delete a; what destructor would it call?Donelson
Destruction is always in reverse order of construction. In this case, class A destructor must be virtual which enforces Child destructor called first followed by A destructor. If the A class destructor is not virtual then the behavior is undefined.Privation
It will call the child's destructor as you have made the parent class destructor virtual. After that, the parent class's destructor.Mott
Having both the destructor and the pure virtual doWork(), in A, leads to a vtable error. How can i define a virtual destructor so that: A *a = new Child(); delete a; leads to a call to Child::~Child()?Donelson
The solution is to place A::~A(){} in Child.cppDonelson
H
2

Make sure to delete any "*.gch" files if none of the other responses help you.

Honeyed answered 11/6, 2014 at 4:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.