ultrakult
ultrakult

Reputation: 37

Does a pure virtual destructor suffice to make a class abstract?

I hope this is not becoming a 'duplicate', as there are so many questions about (pure) virtual destructures (yes, I do know about them).

I want to build an 'interface' (-> abstract class) with a bunch of methods, which can be reimplemented, but don't need to. So I have like:

class IBase
{
public:
  virtual bool doThis() { return true; }
  virtual bool doThat() { return true; }
}

And I'm giving a bunch of implementations, some use doThis some use doThat. That's why the 'interface' methods are just virtual and not pure. Like:

class Derived1 : public IBase
{
public:
  bool doThis() override { return doSomething(); }
}

class Derived2 : public IBase
{
public:
  bool doThat() override { return doSomethingElse(); }
}

The problem: This IBase class is instantiable, which it must not, because it doesn't do anything...

My question(s): Does it suffice to define a pure virtual destructor virtual ~IBase() = 0 to make it uninstantiable? And/or do I need to delete the standard constructor IBase() = delete?

Maybe I eventually became code-blind for thinking about it for too long, so I'll excuse in advance.

Edit: My initial greeting got cut (by me or SO), so I'll greet y'all now or never: Hey folks!

Upvotes: 3

Views: 105

Answers (3)

Paolo Irrera
Paolo Irrera

Reputation: 253

personally I would avoid making the destructor a pure virtual. In C++ you can define a function that has been declared as virtual. See the following example:

class IBase
{
public:
IBase() = default;
virtual ~IBase() = default;

virtual bool doThis() = 0;

virtual bool doThat() = 0;
};

bool IBase::doThis()
{
    return true;
}

bool IBase::doThat()
{
    return true;
}

class Derived2 : public IBase
{
public:
bool doThat() override { return false; }

bool doThis() override { return IBase::doThis(); } // call parent implementation
};

int main()
{
    Derived2 a;
    std::cout << a.doThat() << std::endl;
    std::cout << a.doThis() << std::endl;
}

However, from a design point of view, a class that derives from a an interface should implement all its method. I therefore suggest you rethinking about your solution, if you can.

Upvotes: 1

lubgr
lubgr

Reputation: 38287

Does it suffice to define a pure virtual destructor virtual ~IBase() = 0 to make it uninstantiable?

Yes. One must note that pure virtual destructors differ from non-special pure virtual functions with respect to their definition: for a destructor, there must be a definition. Therefore, you must add

IBase::~IBase() {}

somewhere. A good read on this topic is GotW 31.

And/or do I need to delete the standard constructor IBase() = delete?

No.

Upvotes: 0

Yes, making the destructor pure is enough to make the class abstract. An abstract class is defined as "has at leat one pure virtual member function."

However, note that you still need to provide an implementation for the pure virtual destructor, otherwise it would not be callable by derived classes. You can do it like this:

class IBase
{
public:
  virtual ~IBase() = 0;
  virtual bool doThis() { return true; }
  virtual bool doThat() { return true; }
}

inline IBase::~IBase() {}

Upvotes: 0

Related Questions