Public and private inheritance in C++ - c++

As we know from the literature for the public inheritance the object of child class (sub-class) also can be considered as the object of base class (super-class). Why the object of the sub-class can’t be considered as an object of super-class, when the inheritance is protected or private?

Because you can't see it:
class Base
{
public: virtual ~Base() {}
};
class PublicDerived: public Base
{ };
class PrivateDerived: private Base
{ };
int main()
{
PublicDerived publicD;
PrivateDerived privateD;
Base& base1 = publicD;
Base& base2 = privateD; // ERROR
}
So you can not use a PrivateDerived object where a Base object could be used.
So it will never act like a Base class object.

In general you will find in literature (and in other answers here) that protected/private inheritance imply that the class cannot be used as a base. The fact (some other answer hints into this) is that only the visibility of the inheritance is affected by the operation. The derived class is a base class, even if external code cannot see it.
Any friend or the class will be able to make use of that relationship:
struct base {
virtual void foo() { std::cout << "base" << std::endl; }
};
void take_base( base& b ) {}
class derived : base // private {
friend base& to_base( derived& );
virtual void foo() { std::cout << "derived" << std::endl; }
public:
base & as_base() { return *this; }
void call_function() { take_base(*this); } // ok: inside derived, it knows that it is
// in fact a base
};
base& to_base( derived& d ) {
return d;
}
int main() {
derived d;
//d.foo(); // error
//take_base(d); // error
take_base( d.as_base() ); // ok, the conversion is performed internally where
// access is granted: print "derived"
take_base( to_base(d) ); // ok, the conversion is performed in a friend function
// that has access: print "derived"
}
Now, while technically this is the case, semantically when you use private inheritance you are trying to model not an is-a but rather a implemented-in-terms-of relationship. This is the important part: while reading code, if you see private inheritance you should not think on is-a but implemented-in-terms-of.

In brief, because private inheritance is inheritance of implementation, not that of interface. A private subclass Derived object is not a Base, but is implemented in terms of Base. The public and protected members of Base are visible for Derived, but they become private, thus inaccessible for the outside world. Thus private inheritance can be thought of as a special form of composition, which is in fact rarely needed in practice. (And protected inheritance is practically never - in fact probably even Bjarne Stroustrup doesn't know what protected inheritance means.)

The "why" is simple when considering how the mechanism works: because protected and private inheritance are meant to work that way.
This is probably not enough to answer the question's intent though. You might ask "and why have private and protected inheritance if you can't use the resulting objects as instances of the base class?"
Well, non-public inheritance is meant to facilitate the "is implemented in terms of" relationship between two classes (whereas public inheritance facilitates the "is-a" relationship). In other words, you intend to reuse part or all of the base class functionality to provide services to your own consumers.
This scenario is almost always better implemented by aggregation instead of inheritance (i.e., having a member object of the "base" class), and I would go so far as to say that non-public inheritance is something better left alone.
Take a look at this for a longer write-up that expands on the above.
Update: as the commenters below state, there are some (admittedly rare) cases where non-public inheritance provides the mechanism for architectural functionality that would not otherwise be possible. Do read them, as exploring the edges of a language can be quite enlightening. But try to do it as little as you can anyway.

public inheritance serves the purpose of the is-a relationship. That is:
class A {};
class B : public A {};
Class B is a version of class A.
private inheritance serves the purpose of the has-a relationship. You can write almost any class using private inheritance using a container model instead:
class A {};
class B : private A {};
can be rewritten (and more often than not, should be rewritten for clarity):
class A {};
class B
{
private:
A a;
};
protected inheritance is similar to private, but in reality should almost never be used (Scott Meyers and Herb Sutter both give reasons for this in their respective books).

You can think of public / protected / private inheritance like accessibility for any class member : it a matter of 'how much you want to show'.
A private (or protected, in a slightly different way) inheritance is a relationship which is not shown the outside world. As such, you can't treat an object of a derived type as its private base, because you don't get to "see" that this relationship even exists.

Why the object of the sub-class can’t
be considered as an object of
super-class, when the inheritance is
protected or private?
It can certainly be considered an object of the super-class. However, such consideration is restricted (by the public/protected/private inhertiance modifier) to but only by itself (private inheritance) or it's sub-classes (protected inheritance).
All external objects are not allowed to considered the class as such, similar to how they not allowed to access protected or private methods or variables. The analogy is rather fitting, if expressed properly.
So, the class itself, its subclasses (and friends) can see this as an is-a relationship, but the outside world is not permitted to do so.
The following code shows this in action:
class Base {
public: virtual ~Base() {}
};
class PublicDerived: public Base
{ };
class ProtectedDerived: protected Base {
void test() {
Base* base2 = this; // OK
}
};
class ProtectedSubClass: public ProtectedDerived {
void test() {
Base* base2 = this; // OK
}
};
class PrivateDerived: private Base {
void test() {
Base* base2 = this; // OK
}
};
class PrivateSubClass: public PrivateDerived {
void test() {
Base* base2 = this; // Error (line 28)
}
};
int main()
{
PublicDerived publicD;
ProtectedDerived protectedD;
PrivateDerived privateD;
Base* base1 = &publicD;
Base* base2 = &protectedD; // Error (line 39)
Base* base3 = &privateD; // Error (line 40)
}
Note that it doesn't matter how the xxxSubClass-classes derive from their super-classes. It's all about how the super-classes derive from Base, which is as it should be.
The compiler complains appropriately:
inherit.cpp(28) : error C2247: 'Base' not accessible because 'PrivateDerived' uses 'private' to inherit from 'Base'
inherit.cpp(1) : see declaration of 'Base'
inherit.cpp(20) : see declaration of 'PrivateDerived'
inherit.cpp(1) : see declaration of 'Base'
inherit.cpp(29) : error C2243: 'type cast' : conversion from 'PrivateSubClass *const ' to 'Base *' exists, but is inaccessible
inherit.cpp(39) : error C2243: 'type cast' : conversion from 'ProtectedDerived *' to 'Base *' exists, but is inaccessible
inherit.cpp(40) : error C2243: 'type cast' : conversion from 'PrivateDerived *' to 'Base *' exists, but is inaccessible

Related

How do you prevent protected members of the base class from still being accessed in the second level of the subclass?

An example to illustrate my problem:
class Base
{
protected:
int x{ 0 };
};
class DerivedClass1 : public Base
{
};
class DerivedClass2 : public DerivedClass1
{
public:
int getX() const
{
return x;
}
};
int main()
{
DerivedClass2 d2{};
int x{ d2.getX() };
return 0;
}
I can access the protected member of Base in theDerivedClass2 class, although the protected members of Base should only be changed in DerivedClass1. By inheriting the variable in Base to DerivedClass1 a class shall be formed, which the DerivedClass2 must not manipulate. In C# this is possible with the private protected keyword, but how can you handle it in C++?
What are the consequences of protected?
It is the very idea of protected to allow all the derived classes to access such members.
While this is a very flexible language feature, it creates a serious weakness in the encapsulation, which encourages breaking the Liskov Substitution Principle (more precisely the history constraint, since a derived class could alter the state of a base object without going through a base class primitive).
How to avoid its drawbacks ?
If you want a stronger encapsulation and restrictive access, you'd need to go to private. This ensure that the inner state of a base class can only be accessed using the public interface. (Note that while it ensures the history constraint, it doesn't on its own guarantee LSP). And the consequence is that no derived class gets access. Not at first derivation, and not later.
Do you need private protected ?
What you want, is a kind of in-between: a weak encapsulation, but not too weak. This doesn't exist in C++. And I'm not sure it would strengthen your design.
But if you need this limitation on exceptional basis, there could be a work-around, playing with the name lookup:
class DerivedClass1 : public Base
{
private:
using Base::x;
// In DerivedClass1 you can still use x.
};
// But it will fail to compile in Derived2
Online demo
But personally I would not advise to go this way. It's error prone (you could forget the using in one sibling derived). The compiler error messages might be misleading. And anyway, private yields more robust design.
You could declare the data member as private and use friend-declarations to explicitly specify which classes may access it though:
class Base
{
friend class DerivedClass1;
private:
int x = 0;
};
class DerivedClass1 : public Base
{
void test() {
cout << x; // OK: DerivedClass1 is a friend of Base
}
};
class DerivedClass2 : public DerivedClass1
{
public:
int getX() const
{
return x; // ERROR: x is a private member
}
};
Inherit a 'private' Base:
class DerivedClass1 : private Base
{
};
Edit: Expose public or protected members in Base through public or protected members in DerivedClass1. DerivedClass1 then has complete control over what Base members can and cannot be accessed by classes inheriting from DerivedClass1.
Whether that's a good solution depends on the complexity of Base.

friendship from derived class method to base class members

I would like to know if there's a way to make a method from a derived class a friend of its base class. Something like:
class Derived;
class Base
{
int i, j;
friend void Derived::f();
protected:
Base();
};
class Derived : public Base
{
public:
void f();
};
The errors I got were:
error: C2027: use of undefined type 'Derived'
see declaration of 'Derived'
error: C2248: 'Base::i' : cannot access private member declared in class 'Base'
see declaration of 'Base::i'
see declaration of 'Base'
error: C2248: 'Base::j' : cannot access private member declared in class 'Base'
see declaration of 'Base::j'
see declaration of 'Base'
error: C2027: use of undefined type 'Derived'
see declaration of 'Derived'
I struggled with it during all the day. Everything I found about friendship use only separated classes, not inheritance.
No there is no direct way : Base needs the definition of Derived::f while Derived also needs the definition of it's Base class.
But it does not matter, you should not do that, you can, in order of preference :
Provide protected accessors in the Base class
Make the entire Derived class a friend (not necessary in general)
You can use an intermediate helper class which only forward the call of this specific method, and give it friendship :
Example here:
class Base;
class Derived;
class Helper final
{
friend class Derived;
public:
void f(Base* base);
private:
Helper() {}
};
class Base
{
int i, j;
friend class Helper;
protected:
Base() {}
};
class Derived : public Base
{
public:
void f();
private:
Helper helper;
};
void Helper::f(Base* base)
{
base->i = 10; base->j = 5;
std::cout << "Help !" ;
}
void Derived::f()
{
helper.f(this);
}
One approach for this kind of problem is to apply the rule "if it's a thing, then it's a class."
#quantdev solution is on those lines.
Based on the comment:
assuming that I have two classes both derived from base class and
having an identical private member. Why not saving some codes by
putting that member in the base class and providing a friend access to
both derived classes that need the member. Assuming that other derived
classes won't be able to access that member at all. That's what I'm
trying to achieve
[I know that this does not answer the specified question, but may be what you need.]
I'd solve that by factoring the common element into an intermediate class:
class Base
{
public:
Base();
virtual ~Base() = 0;
};
class Derived : public Base
{
public:
void f()
{
i = 1;
}
private:
int i, j;
};
class Foo : public Derived
{};
class Bar : public Derived
{};
class Fred : public Base
{};
I don't know if it is possible to do exactly what you want (although it seems to me like it should be) -- and I'd be interested to see other answers that show how if it is -- but there are a few other ways to achieve what you want. I assume you are asking about this situation in general -- that is, you are also interested in the case where there can be many different derived classes, not all of which need, no should have access to the private fields of Base (otherwise you should make these fields protected of course).
First, the easiest thing to do would be to make Derived a friend class to Base, although this feels like a hack (in part because it doesn't allow for any encapsulation of Base with respect to Derived) and is definitely sub-optimal here.
In my opinion, a somewhat better approach in terms of encapsulation would be to make an external "free" (non-member) function that is a friend to Base (and potentially Derived if you need that too). This gets around the circular compiler error, but unfortunately still loses the conceptual semantics of being an "operation on Derived".

C++ protected heritage

I have an abstract class AUnit with variables and getters/setters in virtual pure like this
class AUnit {int var... int getVar() const = 0 ... }
All the data is in protected: except constructor and destructor.
I have Berserk and Tank as child like this
class Berserk : public AUnit
{
...
private:
int getVar() const;
In their .cpp, I write the code of the getters and setters. Nothing special.
But I have one other class (foo for example) like this
class Foo : public Berserk, public Tank
who need to access the data in Berserk or Tank so I changed the private keyword by protected, here is the error :
Tank.hpp:36:25: erreur: ‘virtual int Tank::getY() const’ is protected
error inside the context
As first, I just tried to access the data with the AUnit getter but cause of virtual pure and abstract concepts, I thought to reinterpret_cast my AUnit in his real type after passing getType of AUnit in non-pure and in public. Still not working, its the scheme I told you earlier.
It's just classical heritage, can I have some help ?
Your code snipped is certainly incomplete. My guess is that you have something like this:
int Foo::f(Tank const* tank) {
return tank->getY();
}
(probably, you are doing something more interesting with value than returning it).
Even though access to Tank::getY() is protected, the class Foo won't have access to getY() in the above code because the object pointed to by tank is not known to be a Foo object: a class has only access to protected members in a base object of its own type! That is, the following would be OK:
int Foo::f(Foo const* foo) {
return foo->getY();
}
So far the only good use I have found for protected a virtual member functions which have a reasonable an non-trivial implementation in a base class and which are called from a [further] derived class as part of overriding the member. This way, functionality can be added and the common logic can be used (of course, any virtual function is not public but rather private or protected).
It is generally a bad idea to give the overriding function a stricter access protection than the function it overrides. Consider:
class Base {
public:
virtual void f() {}
};
class Derived : public Base {
private:
virtual void f() {} // overrides Base::f
};
Derived d;
d.f(); // error - f is private
Base* pb = &d;
pb->f(); // OK - calls d.f()
To avoid such paradoxes, it is prudent to put overrides at the same access level as the original (or the more relaxed access level, though that's somewhat unusual).

Prevent class inheritance in C++

Recently one of my friend asked me how to prevent class inheritance in C++. He wanted the compilation to fail.
I was thinking about it and found 3 answers. Not sure which is the best one.
1) Private Constructor(s)
class CBase
{
public:
static CBase* CreateInstance()
{
CBase* b1 = new CBase();
return b1;
}
private:
CBase() { }
CBase(CBase3) { }
CBase& operator=(CBase&) { }
};
2) Using CSealed base class, private ctor & virtual inheritance
class CSealed
{
private:
CSealed() {
}
friend class CBase;
};
class CBase : virtual CSealed
{
public:
CBase() {
}
};
3) Using a CSealed base class, protected ctor & virtual inheritance
class CSealed
{
protected:
CSealed() {
}
};
class CBase : virtual CSealed
{
public:
CBase() {
}
};
All the above methods make sure that CBase class cannot be inherited further.
My Question is:
Which is the best method ? Any other methods available ?
Method 2 & 3 will not work unless the CSealed class is inherited virutally. Why is that ? Does it have anything to do with vdisp ptr ??
PS:
The above program was compiled in MS C++ compiler (Visual Studio).
reference : http://www.codeguru.com/forum/archive/index.php/t-321146.html
As of C++11, you can add the final keyword to your class, eg
class CBase final
{
...
The main reason I can see for wanting to do this (and the reason I came looking for this question) is to mark a class as non subclassable so you can safely use a non-virtual destructor and avoid a vtable altogether.
You can't prevent inheritance (before C++11's final keyword) - you can only prevent instantiation of inherited classes. In other words, there is no way of preventing:
class A { ... };
class B : public A { ... };
The best you can do is prevent objects of type B from being instantiated. That being the case, I suggest you take kts's advice and document the fact that A (or whatever) is not intended to be used for inheritance, give it a non-virtual destructor, and no other virtual functions, and leave it at that.
You are going through contortions to prevent further subclassing. Why? Document the fact that the class isn't extensible and make the dtor non-virtual. In the spirit of c, if someone really wants to ignore the way you intended this to be used why stop them? (I never saw the point of final classes/methods in java either).
//Note: this class is not designed to be extended. (Hence the non-virtual dtor)
struct DontExtened
{
DontExtened();
/*NOT VIRTUAL*/
~DontExtened();
...
};
1) is a matter of taste. If I see it correctly, your more fancy 2nd and 3rd solutions move the error in certain circumstances from link time to compile time, which in general should be better.
2) Virtual inheritance is needed to force the responsibility to initialize the (virtual) base class to the most derived class from where the base class ctor is no longer reachable.
To answer your question, you can't inherit from CBase because in virtual inheritance a derived class would need to have direct access to the class from which it was inherited virtually. In this case, a class that would derive from CBase would need to have direct access to CSealed which it can't since the constructor is private.
Though I don't see the usefulness of it all (ie: stopping inheritance) you can generalize using templates (I don't think it compiles on all compilers but it does with MSVC)
template<class T>
class CSealed
{
friend T; // Don't do friend class T because it won't compile
CSealed() {}
};
class CBase : private virtual CSealed<CBase>
{
};
If you can, I'd go for the first option (private constructor). The reason is that pretty much any experienced C++ programmer will see that at a glance and be able to recognize that you are trying to prevent subclassing.
There might be other more tricky methods to prevent subclassing, but in this case the simpler the better.
From C++11 onward, there is a clean solution that I am surprise not to see here. We can make the class final preventing any further inheritance.
class Foo final {};
class Bar: public Foo {}; // Fails to compile as Foo is marked as final
class myclass;
class my_lock {
friend class myclass;
private:
my_lock() {}
my_lock(const my_lock&) {}
};
class myclass : public virtual my_lock {
// ...
public:
myclass();
myclass(char*);
// ...
};
myclass m;
class Der : public myclass { };
Der dd; // error Der::dd() cannot access
// my_lock::my_lock(): private member
I found it here to give credit. I am posting here just other people can easily access
http://www.devx.com/tips/Tip/38482
To elaborate on Francis' answer: if class Bottom derives from class Middle, which virtually inherits from class Top, it is that most derived class (Bottom) that is responsible for constructing the virtually inherited base class (Top). Otherwise, in the multiple-inheritance/diamond-of-death scenario (where virtual inheritance is classically used), the compiler wouldn't know which of the two "middle" classes should construct the single base class. The Middle's constructor's call to the Top's constructor is therefore ignored when Middle is being constructed from Bottom:
class Top {
public:
Top() {}
}
class Middle: virtual public Top {
public:
Middle(): Top() {} // Top() is ignored if Middle constructed through Bottom()
}
class Bottom: public Middle {
public:
Bottom(): Middle(), Top() {}
}
So, in the the approach 2) or 3) in your question, Bottom() can't call Top() because it's inherited privately (by default, like in your code, but it's worth making it explicit) in Middle and thus is not visible in Bottom. (source)

Interfaces in c++

I would like to use interfaces in c++ like in java or in c#. I decided to use purely abstract classes with multiple inheritance, but something is terribly wrong when I specialize the interface:
class Interface
{
public:
virtual int method() = 0;
};
// Default implementation.
class Base: virtual public Interface
{
public:
virtual int method() {return 27;}
};
// specialized interface
class Interface2: public Interface
{
public:
virtual int method() = 0;
// some other methods here
};
// concrete class - not specialised - OK
class Class: public virtual Interface, public virtual Base
{
};
// concrete class - specialised
class Class2: public Interface2, public Base
{
};
int main()
{
Class c;
Class2 c2;
return 0;
}
Warning 1 warning C4250: 'Class' : inherits 'Base::Base::method' via dominance 30
Error 2 error C2259: 'Class2' : cannot instantiate abstract class 42
What is the proper way to do this?
Class2 inherits from an abstract class (Interface2) but does not implement the pure virtual method, so it remains as an abstract class.
Heh heh, this problem tickles something buried deep in my head somewhere. I can't quite put my finger on it but I think it's to do with defining an interface heirarchy and then inheriting both an interface and an implementation. You then avoid having to implement all functions with by forwarding calls to a base class. I think.
I think this simple example shows the same thing, but is maybe a bit easier to understand because it uses things that can be easily visualized: (please forgive the struct laziness)
#include <iostream>
using namespace std;
struct Vehicle
{
virtual void Drive() = 0;
};
struct VehicleImp : virtual public Vehicle
{
virtual void Drive()
{
cout << "VehicleImp::Drive\n";
}
};
struct Tank : virtual public Vehicle
{
virtual void RotateTurret() = 0;
};
struct TankImp : public Tank, public VehicleImp
{
virtual void RotateTurret()
{
cout << "TankImp::RotateTurret\n";
}
// Could override Drive if we wanted
};
int _tmain(int argc, _TCHAR* argv[])
{
TankImp myTank;
myTank.Drive(); // VehicleImp::Drive
myTank.RotateTurret(); // TankImp::RotateTurret
return 0;
}
TankImp has essentially inherited the Tank interface and the Vehicle implementation.
Now, I'm pretty sure this is a well known and acceptable thing in OO circles (but I don't know if it has a fancy name), so the dreaded diamond thing is ok in this case, and you can safely suppress the dominance warning because it's what you want to happen in this case.
Hope that somehow helps point you in the right direction!
BTW, your code didn't compile because you hadn't implemented the pure virtual "method" in Class2.
EDIT:
Ok I think I understand your problem better now and I think the mistake is in Interface2. Try changing it to this:
// specialized interface
class Interface2: public virtual Interface // ADDED VIRTUAL
{
public:
//virtual int method() = 0; COMMENTED THIS OUT
// some other methods here
};
Interface2 should not have the pure virtual defintion of method, since that is already in Interface.
The inheritance of Interface needs to be virtual otherwise you will have an ambiguity with Base::method when you derive from Interface2 and Base in Class2.
Now you should find it will compile, possibly with dominance warnings, and when you call c2.method(), you get 27.
Based on this comment
If the method is not reimplemented in Class2 or Class (it is not in
this case) Base::method() will be called. Otherwise the reimplementation
will be called. There is an interface hierarchy with a common base
dumb implementation.
– danatel 16 mins ago
That's not what you got, you don't have a common base, you've got
Interface -> Interface2 -> Class2
Interface -> Base -> Class2
The interface is not 'merged' in the derivation tree, interface2 does not inherit virtually from interface, so it'll have its own interface super class.
It's like the pure virtual method() exists twice in Class2, once implemented via Class, and once not-implemented.
And even if you had inherited virtually, the common base (Interface) still would not have an implementation
If Base contains trivial operations that should be usuable in the whole hierarchy, then why not have Base as your startpoint? (even if still pure virtual with an implementation).
If this was just a very simple example to make the question short, something like the Bridge Pattern might be more usefull. But it's hard to guide you further without knowing more.
You should also look at defining a virtual destructor in your Interface if you might be deleting using an Interface or Base pointer.
Without a virtual destructor you will have problems if you do something like:
Base *b = new Class2();
delete b;
Regarding Class: All you need to do is derive Class from Base -- the fact that it implements Interface is implied, and in fact, inescapable:
class Class: public Base // virtual inheritance is unnecessary here
{
};
Class will inherit method() from Base as desired.
Regarding Class2:
Disclaimer: Negative result ahead
Based on your comment on Tom's answer, I thought I had the answer for Class2:
// concrete class - specialised
class Class2: public Interface2, public Base
{
public:
using Base::method; // "Imports" all members named "method" from Base
};
But actually, this doesn't work. Grovelling through the C++ standard reveals that
section 7.3.3, paragraph 14 explains that using can't be used to resolve ambiguous accesses to inherited members:
... [Note: because a using-declaration designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declaration cannot be used to resolve inherited member ambiguities. ...]
It seems that the only way to get the desired behaviour in Class2 is to manually forward the method:
// concrete class - specialised
class Class2: public Interface2, public Base
{
public:
virtual int method() { return Base::method(); }
};
Regarding virtual inheritance: You don't need it for Class's declaration, but you probably do need it for Interface2's declaration to ensure that Class2 only has a single subobject of type Interface -- as it stands, every Class2 object has two subobjects of this type. (Although that won't cause problems if Interface is in fact a pure interface, lacking member variables.) If it helps, draw a diagram: every time a base class appears without the keyword virtual, it appears as a distinct object; all base classes that appear with the keyword virtual are condensed into one object.
[UPDATE: markh44's excellent answer shows that the above approach (of making Interface2 inherit virtually from Interface) will in fact allow Class2 to automatically inherit the implementation of method() from Base! Problem solved!]
This answer in a different forum seems to tackle the exact problem you mention.
In general, you should avoid the diamond inhertance pattern:
Interface
/ \
Base Interface2
\ /
Class2
This will cause you call kinds of grief down the road if you're not careful. Ambiguity will bite you.
In your specific instance there's no need for Interface2 to inherit from Interface. Interface2 doesn't need to specify "method" since it's abstract. Remove the inheritance between Interface and Interface2 to break the diamond. Then you're hierarchy looks like:
Interface Interface Interface2
| | |
Base Base |
| \ /
Class Class2
And your implementation looks like:
// concrete class - not specialised - OK
class Class: public Base
{
};
// concrete class - specialised
class Class2: public Base, public Interface2
{
virtual int method() {return 35;}
virtual void Inteface2Method { ... }
};