notadam
notadam

Reputation: 2854

Is there a way to prevent calls to a specific inherited function in a derived class?

Consider the following:

class base {

    // base class

public:
    void doBaseStuff() {
        /* do something basic */
    }
private:
    int someDataMember;
};

class derived : public base {

    // this class inherits 'doBaseStuff()' as well as 'someDataMember'

public:
    void doDerivedStuff() {
        /* do something in addition that only this type of derived class can do */
    }
};

class specialDerived : public base {

    // say 'doBaseStuff()' doesn't make sense in the context of this class!
    // we do not want to inherit that function here
    // is there a way to prevent instances of this class from calling it?
    // we still want 'someDataMember', so we must derive from the base class

public:
    void doSpecialStuff() {
        /* do something in addition that only this special derived class can do */
    }
};

There's a class that serves as a common base class for multiple other classes. But let's say one of the base class' member functions it NOT wanted in one of the derived classes. Is there a way to explicitly ban an inherited function in a derived class?

Realisticly we could be talking about a base class that has a 1000 members, and we want to inherit 999 of them, so simply abandoning inheritance and just duplicating all the code will result in very bad code maintainability.

Making that function in the base class virtual, and providing a dummy implementation of it in the specialDerived class would work. But what if that function has an actual return type, instead of void? The specialDerived class would then have to provide an implementation that returns something. The caller then could assume that the value they got is something meaningful, when it's really not, and that's a problem.

Simply implementing the virtual function in specialDerived with a single throw in the body could be a solution, as long as some documentation exists that explicitly states that calling this function on objects of this specific derived type has no meaning, and that this operation will throw. I think this is one possible solution, but I'm not sure if it's the best way to go.

Upvotes: 3

Views: 1511

Answers (2)

Paul Groke
Paul Groke

Reputation: 6447

  1. Declare doBaseStuff protected in base
  2. Derive a new class base2 from base which just makes doBaseStuff public
  3. Derive the 999 classes from base2 instead of base
  4. Derive the one class from base

Like so:

class base {
protected:
    void doBaseStuff() {
        /* do something basic */
    }
private:
    int someDataMember;
};

class base2 : public base {
public:
    using base::doBaseStuff; // make it public
};

class derived : public base2 {
   // ...
};

class specialDerived : public base {
   // doBaseStuff not public here since we're derived only from base (and not base2) and didn't make it public ourself
};

Upvotes: 1

ex-bart
ex-bart

Reputation: 1372

I'm assuming you just want to make sure the method is not called accidentially, i.e. a compilation error when it gets called is perfect.

You can simply override doBaseStuff in specialDerived with a deleted definition:

class specialDerived : public base {
  void doBaseStuff() = delete;

public:
  void doSpecialStuff() {
      /* do something in addition that only this special derived class can do */
  }
};

That will prevent anyone from using specialDerived::doBaseStuff. It is still possible to convert a reference to specialDerived to a reference to base and call doBaseStuff on the result, but that can't be avoided without making doBaseStuff virtual.

Upvotes: 2

Related Questions