2

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!

ultrakult
  • 27
  • 1
  • 9
  • "which it must not" this is a completely arbitrary requirement. "because it doesn't do anything" the number zero, the empty set, the identity function all "do nothing", in a sense, but we still keep them around. – n. m. could be an AI Aug 23 '18 at 09:02

3 Answers3

1

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.

Paolo Irrera
  • 253
  • 1
  • 10
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() {}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

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.

lubgr
  • 37,368
  • 3
  • 66
  • 117