3

If a parent class has a pure virtual destructor, how can I proper inherit from it? I have a header file (generated by IBM Rational Rose) which looks like this:

class MyClass{
protected:
  inline MyClass() {};
  MyClass(const MyClass&);
  MyClass& operator=(const MyClass&);
public:
  inline virtual ~MyClass() = 0;
  virtual void someMethod() = 0;
};

Now I want to implement this pure-abstract class - i.e.

class MyClassImpl : public MyClass {
public:
  MyClassImpl(){}
  virtual void someMethod() {}
};

int main(int argc, char*argv[]) {
  MyClassImpl impl;
  return 0;
}

But whatever I try (i.e. define a destructor in MyClassImpl; virtual/non-virtual), I keep getting the error message: error LNK2019: unresolved external symbol "public: virtual __thiscall MyClass::~MyClass(void)" (??1MyClass@@UAE@XZ) referenced in function "public: virtual __thiscall MyClassImpl::~MyClassImpl(void)" (??1MyClassImpl@@UAE@XZ).

Is there any way to implement MyClassImpl without changes to MyClass?

Constantin
  • 8,721
  • 13
  • 75
  • 126
  • What compiler are you using? Looks like msvc but just to confirm. – Darko Miletic Nov 26 '15 at 22:28
  • You cannot destroy an instance of a class that has no destructor. You could only ever create one dynamically and then leak it. – Kerrek SB Nov 26 '15 at 22:32
  • Since 'MyClass::~MyClass( void )' cannot be resolved. Define that method in the header file or in a separate file like @MinorThreat posted. –  Nov 27 '15 at 00:59

3 Answers3

6

You must define the destructor even if it is pure virtual (uniquely).

Add

MyClass::~MyClass() {}

in exactly one .CPP file.

(See for example http://en.cppreference.com/w/cpp/language/destructor under "Pure virtual destructors". Also Why do we need a pure virtual destructor in C++?.)

Community
  • 1
  • 1
Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
2

Rather declare your virtual destructor like this, with a body:

inline virtual ~MyClass() {};
inline virtual ~MyClass() = default; // C++11

It has to be implemented (not just declared), otherwise, there will be no way to destruct MyClass and its derived classes (your declaration disables default-generated destructor, but does not provide substituting implementation).

Note that virtual member function can still have an implementation, so you can have:

inline virtual ~MyClass() = 0;

and

virtual MyClass::~MyClass() {}; // defined in .h file because of inline
LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • 1
    `= 0;` as in OP's code, forces the derived class to override the destructor. Presumably this is intentional (there's no other reason why someone would do this) . Your first suggestion changes the behaviour. (Also, on your first two lines `inline` is redundant , providing the body inline implies `inline`) – M.M Nov 26 '15 at 23:05
2

C++ compiler adds some implicit autogenerated code during compilation.

class MyClassImpl : public MyClass {
public:
  MyClassImpl(){}
  virtual void someMethod() {}

  // Begin autogenerated code
  virtual ~MyClassImpl() {
    MyClass::~MyClass(); // <- This will break because your parent class
                         // lacks any destructor body and linker will             
                         // report the missing symbol.
  }
  // End autogenerated code

};

Luckily for you, you can define destructor body in any cpp file without touching files generated by Rational Rose. For example, you can add this line near your main() function.

MyClass::~MyClass(){} // Empty destructor
Minor Threat
  • 2,025
  • 1
  • 18
  • 32