Reputation: 1430
Consider the following three programs in C++:
struct base{
virtual ~base() =0;
};
struct derived: public base{
~derived();
};
derived::~derived(){}
int main(){}
struct base{
virtual ~base() =0;
};
struct derived: public base{
~derived(){}
};
int main(){}
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
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
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