lurscher
lurscher

Reputation: 26943

does it make sense to inherit privately from an abstract (pure virtual) class?

suppose this construct

struct InterfaceForFoo
{
    virtual void GetItDone() = 0;
};


class APoliticallyCorrectImplementationOfFooRelatedThings : private InterfaceForFoo
{

  public:
    void GetItDone() { /*do the thing already*/ };   
};

Now, i'm wondering if inheriting privately from an interface in this way do have any useful scenarios.

Upvotes: 4

Views: 973

Answers (5)

The question is why should it matter that the base class has only pure virtual methods?

The two things are almost unrelated. Private means that it is an implementation detail of your class, and not part of the public interface, but you might want to implement an interface as an implementation detail. Consider that you write a class, and that you decide to implement the functionality by means of a library that requires you to implement an interface. That is an implementation detail, there is no need to make the inheritance public just because the interface has only pure virtual functions.

Upvotes: 2

Dietrich Epp
Dietrich Epp

Reputation: 213308

Huh, everyone here says "no". I say "yes, it does make sense."

class VirtualBase {
public:
    virtual void vmethod() = 0;
    // If "global" is an instance of Concrete, then you can still access
    // VirtualBase's public members, even though they're private members for Concrete
    static VirtualBase *global;
};

// This can also access all of VirtualBase's public members,
// even if an instance of Concrete is passed in,
void someComplicatedFunction(VirtualBase &obj, ...);

class Concrete : private VirtualBase {
private:
    virtual void vmethod();
public:
    void cmethod() {
        // This assignment can only be done by Concrete or friends of Concrete
        VirtualBase::global = this;
        // This can also only be done by Concrete and friends
        someComplicatedFunction(*this);
    }
};

Making inheritance private doesn't mean that you can't access the members of VirtualBase from outside the class, it only means that you can't access those members through a reference to Concrete. However, Concrete and its friends can cast instances of Concrete to VirtualBase, and then anybody can access public members. Simply,

Concrete *obj = new Concrete;
obj->vmethod(); // error, vmethod is private

VirtualBase *obj = VirtualBase::global;
obj->vmethod(); // OK, even if "obj" is really an instance of Concrete

Upvotes: 6

Nicklas A.
Nicklas A.

Reputation: 7061

Not really. If you need a function, you implement it. It makes no sense to force a function that cannot be used by other classes.

Why you would inherit privately from an interface, I don't know; that kind of defeats the purpose of interfaces.

If it's not an interface, but instead a class, it makes sense:

class A {
    virtual void foo() = 0;

    void bar() {
        foo();
    }
};

class B : private A {
    virtual void foo() {

    }
};

Upvotes: -1

iammilind
iammilind

Reputation: 69988

On object oriented aspect there is no use case for such private inheritance for an abstract class.

However, if you want to mandate that you child class must derive certain methods then you can use this. For example:

struct implement_size
{
  virtual size_t size () = 0;
};

class MyVector : private implement_size
{
public:
  size_t size () { ... } // mandatory to implement size()
}

class MyString : private implement_size
{
public:
  size_t size () { ... } // mandatory to implement size()
};

So, it just helps to maintain the personal coding discipline. Message with this example is that, inheritance is not just meant for object oriented purpose. You can even use inheritance for stopping inheritance chain (something like Java final).

Upvotes: 1

Xeo
Xeo

Reputation: 131789

Eh? No, that makes absolutely no sense, since the reason you provide an interface is that you want other to use your class through that interface. How would that work if they don't know you implement it?

#include <vector>

class Fooable{
public:
  virtual void foo() = 0;
};

class DoesFoo
  : private Fooable
{
  void foo();
};

int main(){
  std::vector<Fooable*> vf;
  vf.push_back(new DoesFoo()); // nope, doesn't work
  vf[0]->foo();
}

The above example doesn't work because the outside world doesn't know that DoesFoo is a Fooable, as such you cannot new an instance of it and assign it to a Fooable*.

Upvotes: -1

Related Questions