Mathew
Mathew

Reputation: 1430

virtual destrutors vs normal methods in C++

Consider the following three programs in C++:

program 1

struct base{
  virtual ~base() =0;
};

struct derived: public base{
  ~derived();
};

derived::~derived(){}

int main(){}

program 2

struct base{
  virtual ~base() =0;
};

struct derived: public base{
  ~derived(){}
};

int main(){}

program 3

struct base{
  virtual void func() =0;
};

struct derived: public base{
  void func();
};

void derived::func(){}

int main(){}

The programs #2 and #3 compile and run fine however the first gives the following error:

Undefined symbols for architecture x86_64:
  "base::~base()", referenced from:
    derived::~derived() in main-d923b9.o
ls: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I'd like to know why I am unable to define virtual destructors outside of the class definition however I am able to do it inside the class definition. Additionally I can define methods outside the class, just not destructors.

Upvotes: 4

Views: 165

Answers (2)

Spock77
Spock77

Reputation: 3325

The answer to why program 2 builds lays in how link works. When function definition is outside the class declaration, linker needs to create a body of the function in the final binary file so it needs to have ~base() definition as well.

If you put in case 2 derived d; in main body, you'll get the same error as in case 1 as the linker will have to create the derived member functions definitions and will need ~base() body as in case 1.

Upvotes: 1

YSC
YSC

Reputation: 40070

This is wrong

struct base{
  virtual ~base() =0;
};

because base::~base is not defined. Even though it has been declared as a pure virtual, it needs to be defined (outside of the class, there is no syntaxic way to declare a function as pure virtual and define it inline) so derived can inherit from it:

struct base
{
    virtual ~base() = 0;
};

base::~base() {}

I'd like to know why I am unable to define virtual destructors outside of the class definition

Well, you can: I just did.


Then, why do you need to implement a function (~base) which has been declared pure virtual?

Since derived inherit from base, when an object of type derived is destructed, it necessarily calls base's destructor. This is how inheritance work. In a sense, derived::~derived needs to link with base::~base. Even though base::~base is a pure virtual (meaning a class inheriting from base is not a complete type unless it defines a destructor) it needs to be defined so ~derived finds it and the linker become happy.

Upvotes: 4

Related Questions