Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it dangerous to create pure virtual function of a virtual function?

Let us suppose that we have an abstract class NonEditableSuperBase from which we create another abstract class MyBase.

The first class NonEditableSuperBase has a virtual function (non pure virtual). However, I want to force that if someone creates a class that derives from MyBase, he/she must provide an implementation to the mentioned function.

Hence, my idea is to define the function as pure virtual in MyBase.

My question: Is it a bad idea given that it was just virtual in NonEditableSuperBase?

Example:

//NonEditableSuperBase.h
class NonEditableSuperBase
{
  ...
  public:
    virtual int someMethod(); //It has an implementation, suppose {return 42;}
};

//MyBase.h
class MyBase: public NonEditableSuperBase
{
  public:
     explicit MyBase();       
     virtual ~MyBase() = default;       
     virtual int someMethod() = 0;  //I make it pure virtual
};

//MyBase.cpp
MyBase::MyBase() : NonEditableSuperBase() { }

//Now someone creates a derived class from MyBase.
class SuperDerived : public MyBase
{
  public:
    explicit SuperDerived();
    int someMethod(); //The user must create an implementation of the function
};

Update: As an example, in my case I want to create some derived classes from the QAbstractTableModel class of the Qt framework. To reuse some code I want to create an intermediate abstract class.

QAbstractTableModel <- MyAbstractModel <- MyModelA (or MyModelB ... etc).

However, I want to ensure that the models (MyModelA, MyModelB) re-implement some of the virtual functions of QAbstractTableModel (like the ::index() function) because some of the additional methods of MyAbstractModel requires specific implementations of the primer functions.

like image 260
pablo_worker Avatar asked Mar 31 '17 14:03

pablo_worker


People also ask

What are the implications of making a function a pure virtual function?

A pure virtual function makes it so the base class can not be instantiated, and the derived classes are forced to define these functions before they can be instantiated. This helps ensure the derived classes do not forget to redefine functions that the base class was expecting them to.

When should we use a virtual vs a pure virtual function?

A virtual function is a member function of base class which can be redefined by derived class. A pure virtual function is a member function of base class whose only declaration is provided in base class and should be defined in derived class otherwise derived class also becomes abstract.

What happens when a virtual function has a virtual function in it?

Whenever the class has at least one virtual function. Having virtual functions indicate that a class is meant to act as an interface to derived classes, and when it is, an object of a derived class may be destroyed through a pointer to the base. For example: class Base {

Can pure virtual function be protected?

A virtual function can be private as C++ has access control, but not visibility control. As mentioned virtual functions can be overridden by the derived class but under all circumstances will only be called within the base class. Example: C++


2 Answers

From ISO IEC 14882 2014:

§ 10.4 says:

5 [ Note: An abstract class can be derived from a class that is not abstract, and a pure virtual function may override a virtual function which is not pure. —end note ]

So It's perfectly possible to do that.

Example of use case:

You can have a basic type, that is implemented as a concrete type (base class). Now, for subtypes, we might be in a need of further additional information. So, we can have an abstract intermediate object to meet our needs.

like image 57
HDJEMAI Avatar answered Oct 05 '22 06:10

HDJEMAI


[I'm assuming that the intent was for MyBase to publicly derive from NonEditableSuperBase, which is not what the code sample in the question actually does.]

It doesn't seem inherently dangerous, but consider that a class like SuperDerived that derives from MyBase could explicitly choose to use the NonEditableSuperBase implementation.

class SuperDerived : public MyBase {
  public:
    using NonEditableSuperBase::someMethod;
    // Or, explicitly:
    // int someMethod() override { return NonEditableSuperBase::someMethod(); }
};

This satisfies the pure-virtual requirement imposed by MyBase but acts exactly as if MyBase didn't have that requirement. You've made the author of SuperDerived do something, but you haven't actually prevented them from using the ultimate base class's implementation.

like image 22
Adrian McCarthy Avatar answered Oct 05 '22 04:10

Adrian McCarthy