Can you inherit the same class twice? E.g. :
class Base {
};
class Foo : public Base {
};
class Bar : public Base {
};
class Baz : public Foo, public Bar {
//is this legal?
// are there restrictions on Base
// (e.g. only virtual methods or a virtual base)?
};
Yes it is legal, and no there are no restrictions on Base.
You should however be aware that this causes two different objects of type Base to exist within Baz, which will require you to use qualified names to tell C++ which version of Base you mean, when you try to access its members.
C++ provides a mechanism called virtual inheritance to solve this problem (if it is a problem for you):
class Base { };
class Foo : public virtual Base { };
class Bar : public virtual Base { };
class Baz : public Foo, public Bar { };
This will share the Base object between the Foo and Bar objects within Baz
C++ does support multiple inheritance.
The syntax for class Baz is correct.
See this tutorial for some caveats and more information: http://www.cprogramming.com/tutorial/multiple_inheritance.html
Yes, it's legal to inherit the same class twice.
If the inheritance is non-virtual, as in your example (I just fixed the syntax and formatting),
class Base {};
class Foo : public Base {};
class Bar : public Base {};
class Baz : public Foo, public Bar {};
then it's generally necessary to qualify any use of something from such duplicate base.
If however each direct inheritance of the common base is virtual (using the keyword virtual), then there is only one common sub-object of the common base. This is the so called diamond pattern of inheritance in C++. It's a bit tricky, e.g. in that it yields at least one sub-object spread over a non-contiguous region of memory, and in that it's the most derived class that is responsible for initializing the common virtual base. Also it introduces some inefficiency and is associated with some compiler bugs. So it's seldom used, but sometimes it's necessary – e.g., it can emulate Java interface inheritance, and it can be used to emulate Java final (not necessary in C++11).
Yes, it is legal, but having two subobjects of the same Base class causes many difficulties, because you always must explicitly say which one you want, using the scope operator ::.
Baz x;
Base& y = x; // Illegal because ambiguous.
Base& y = (Bar&)x; // Now unambiguous.
Part of that trouble can be solved by inheriting Base using virtual inheritance, which makes sure only exactly one Base.subobject exists.
In that case, the virtual base is always initialised by the most derived constructor, before all non-virtual bases.
class Base {}
class Foo : public virtual Base {}
class Bar : public virtual Base {}
class Baz : public Foo, public Bar {}
Baz x;
Base& y = x; // Legal, because even though both direct bases inherit from `Base`,
// they do so virtually, thus there is only one Base subobject
Base& y = (Bar&)x; // Still unambiguous.
Now, if Foo used protected or private inheritance, you could not cast down to Foo::Derived in Baz or completely outside in the first (non-virtual) example.
In the virtual example, you could, because that sub-object is also reachable using Bar, and the most accessible path determines the access rights.
This is legal.
But restrictions arise when classes are labeled protected and private classes before it. For this, its respective functions and attributes are protected and private.
Related
How is the folloing code working? MakeFinal constructor is protected, so it should not be accessible to FinalUser class. But I didn't get any build or execution error.
class MakeFinal
{
protected:
MakeFinal(void) {};
public:
~MakeFinal(void) {};
};
class Final : virtual public MakeFinal
{
public:
Final(void) {};
~Final(void) {};
};
class FinalUser : public Final
{
public:
FinalUser(void) {};
~FinalUser(void) {};
};
int main()
{
FinalUser *finalUserHeap_ = new FinalUser();
return 0;
}
A virtual base class is initialized by the single most derived class' constructor's member initializer list.
Because the virtual base can be a common base-class object for multiple derived classes, and the initializations specified by those derived classes can conflict.
The initialization specification in the most derived class acts conceptually as if the most derived class was derived directly from the virtual base class, i.e.
FinalUser(void) {};
… is equivalent to
FinalUser(): MakeFinal() {}
Since the MakeFinal constructor is protected, it's available to all derived classes.
That includes that it's available to class FinalUser.
In other news:
The names in this code indicate that it's about using a C++03 trick for creating a class that can't be (usefully) derived from, a “final” class. The trick is essentially to have a class template that can act as most derived class and that has the necessary friend-ship to access the for other classes inaccessible constructor of the virtual base class. C++11 introduced the keyword final to do that more easily, and without the overhead of virtual inheritance.
You need to know the next:
If the inheritance is public, everything that is aware of Base and Child is also aware that Child inherits from Base.
If the inheritance is protected, only Child, and its children, are aware that they inherit from Base.
If the inheritance is private, no one other than Child is aware of the inheritance.
#Anzurio answer in Difference between private, public, and protected inheritance
According this. You need to use private if you want that FinalUser class donot have access to MakeFinal.
Derived classes have access to protected members of their base classes. That's the difference between protected and private.
Consider the following code:
class A {
};
class B : public A {
};
class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};
In this case GCC (4.8.1, C++99) gives me the correct error (I understand this behavior):
prog.cpp:12:8: error: type ‘a’ is not a direct base of ‘c’
However if the inheritance between b and a is virtual, this does not happen:
class A {
};
class B : virtual public A {
};
class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};
Why does this work?
Is A now considered a direct base to C by the compiler?
In general, because this is how C++ tries to resolve the diamond inheritance problem http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (whether or it is a good or bad solution is left as an exercise to the reader).
All inheritance is a combination of an is-a and a has-a relationship...you must instantiate an instance of the parent. If you have the following classes:
class a;
class b : a;
class c : a;
class d : b,c;
Then you've instantiated an a for each b and c. d will not know which a to use.
C++ solves this by allowing virtual inheritance, which is high-overhead inheritance that allows b and c to share the same a if inherited in d (it is much more complicated than that, but you can read up on that on your own).
The most derived type in the chain needs to be able to override the instantiation of the shared class to control disparities in the way that the shared class is inherited in the parent classes. Take the following example:
class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}
If d did not define what a was instantiated as, it would have definitions for conflicting instantiations (from b and c). C++ handles this by forcing the most derived class in the inheritance chain to instantiate all parent classes (the above would barf if d did NOT explicitly instantiate a, though if a supplied a default constructor that could be implicitly used) and ignoring all parent instantiations.
Why does this work?
According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type".
Virtual base is shared between all classes that derive from it for the instance of the object. Since a constructor may only be called once for a given instaniation of an object, you have to explicitly call the constructor in the most derived class because the compiler doesn't know how many classes share the virtual base. This is because the compiler will start from the most base class's constructor and work to the most derived class. Classes that inherit from a virtual base class directly, will not, by the standard, call their virtual base classes constructor, so it must be called explicitly.
From N3337, 12.6.2
Initializing bases and members
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Perhaps someone who has better version of Standard can verify this.
I'm having this kind of code:
class Ref {<undefined>};
Ref refObjectForA, refObjectForB;
class Base
{
public:
Base(const Ref & iRef) : _ref(iRef) {}
virtual ~Base() {}
const Ref & ref;
};
class A: public Base
{
public:
A() : Base(refObjectForA) {}
virtual ~A() {}
};
class B: public A
{
public:
B() : Base(refObjectForB) {} // won't compile: Base is not direct base of B
virtual ~B() {}
};
As the attribute is a reference, I think I can only set it in constructor, so I need to call Base constructor in B().
I've found two ways: providing a "forward" constructor in A (but this implies adding code in all classes that might be inherited):
A(const Ref& iRef): Base(iRef)
or using virtual inheritance:
class A: public virtual Base
Second option allows more straightforward code in B implementation but I'm wondering if I'm misusing virtual inheritance in an ugly trick or if it is a valid usecase.
Can I use virtual inheritance in this case?
If no, for what reason?
One of the "unexpected" behaviors I've found is that it's not possible to static_cast a Base pointer to a B pointer because of the virtual inheritance.
Moreover I'm also wondering why it works (I mean why a B().ref == refObjectForB): I would think that the implicit call to default A() constructor in B() would overwrite the ref attribute after explicit Base constructor, but maybe it's not true with virtual inheritance.
The best option I can see if you want to stick to your inheritance hierarchy is to implement protected constructors taking a reference which they'll forward to the Base class. Making a constructor protected makes sure that a (final) instance can't be constructed using this constructor, so it will only be used in subclasses to initialize the super classes.
With some more or less ugly and dangerous macro, this becomes easy to be written:
#define REF_FORWARD_CTOR(ClassName, DirectSuperClassName) \
protected: ClassName(class Ref &r) : DirectSuperClassName(r) {} \
public:
class A : public Base
{
REF_FORWARD_CTOR(A, Base)
public:
A() : Base(refObjectForA) {} // normal ctor
};
class B : public A
{
REF_FORWARD_CTOR(B, A)
public:
B() : A(refObjectForB) {} // normal ctor
};
An alternative design would be to let A and B both derive (directly) from Base. Then, add functionalities by using multiple inheritance and "common classes", maybe private, depending on what they are for:
class Base {
};
class Common {
// common stuff used by both A and B
};
class A : public Base, public Common {
// no further stuff here
};
class B : public Base, public Common {
// add more stuff, or put it in a common super-class again,
// if some classes want to inherit from B again
};
The problem with this design is that functionality in Common can't access the stuff in A and B. To solve this, do one of the following:
If only static stuff is required: Use CRTP to specify A / B in a concrete Common type: Common<A> can then use A::..., but doesn't have anything to do with a concrete instance of A
If an instance is required: provide a pointer / reference in the constructor of Common (slight overhead)
Putting the first two solutions together: Use CRTP, implement wrapper functions in A and B which call functions in Common<A> and Common<B> providing this (which is a A* or B* via an extra parameter.
Same as above, but the class Common can also be non-templated (no CRTP) if you overload / template these functions on this pointer argument ("CRTP on functions", if you want to call it like that). Code speaks louder than words. (Example code is without your references and focuses on the "common class".)
Yes you can technically use virtual inheritance to achieve the goal of providing the reference in the most derived class.
And yes, that's a design smell.
Your classes should not need to be aware of anything but their immediate bases (virtual inheritance is the exception to the rule, when it's needed for other reasons).
Sticking to the proposed classes hierarchy, in order to solve the problem it is enough to use the "using-declaration" to bring the Base's constructor to the protected part of the class A, i.e.:
class A: public Base
{
public:
A() : Base(refObjectForA) {}
virtual ~A() {}
protected:
using Base::Base;
};
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
I found this code here
class Usable;
class Usable_lock {
friend class Usable;
private:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
class Usable : public virtual Usable_lock {
// ...
public:
Usable();
Usable(char*);
// ...
};
Usable a;
class DD : public Usable { };
DD dd; // error: DD::DD() cannot access
// Usable_lock::Usable_lock(): private member
Could anybody explain me this code?
EDIT: Also another question i have is what is a virtual derivation and when is it needed?
It's a property of virtual derivation.
The idea of virtual derivation is to solve the "Dreaded Diamond Pattern":
struct Base {};
struct D1: Base {};
struct D2: Base {};
struct TopDiamond: D1, D2 {};
The problem here is that TopDiamond has 2 instance of Base here.
To solve this problem, very peculiar "MultiInheritance", C++ uses the virtual keyword and what is thus called "virtual inheritance".
If we change the way D1 and D2 are defined such that:
struct D1: virtual Base {};
struct D2: virtual Base {};
Then there will only be one instance of Base within TopDiamond: the job of actually instantiating it is left to the top-constructor (here TopDiamond).
Thus, the little trick you have shown is simply explained here:
because Usable derives virtually from Usable_lock, it's up to its derived class to instantiate the Usable_lock part of the object
because Usable_lock constructor is private, only itself and Usable (friend) can access the constructor
It's clever, I had never thought of that. I wonder what the cost of virtual inheritance is here (extra memory / speed overhead) ?
class Usable_lock's Constructor is declared under Private
So it is not accessible Outside
Usable_lock class
when you make object of
DD dd;
It will call constructor of Usable and Usable_Lock both (because DD derived from Usable and Usable Derived from Usable_lock)
and thus it can't access Usable_Lock's Constructor.. and it will give you error
There are two points here:
1) Why Usable instance can be created, though it involves private Usable_lock constructor? Because Usable is friend of Usable_lock.
2) Why Usable-derived instance cannot be created? Because it involves private Usable_lock constructor.