I have a question regarding composition and inheritance in C++:
I have a base class 'A' and a derived class 'B' ('B' inherits members from 'A'), is it possible use 'B' as a member of 'A' by composition?
As to "A has B member, B derived from A": Practically, you cannot declare such a thing. If class A has a member of type B, then B needs to be declared before A. If B uses A as a base, A must be declared before B.
As to composition, if you wanted to do such a thing, you could have to use indirection (pointer, smart-pointer, etc).
class B;
class A {
B *b;
};
class B : public A {
};
One might argue that (in C++) using pointers is not composition; however, in Java, all Objects are "pointers", so composition is:
class A {
B b;
}
class B extends A {
}
However you may embed a B* field. Hence a const B& should be possible too, and behave like a B. (Mind I am now a sandbox java programmer.)
class B;
class A {
B& b;
};
BTW you might not even embed an A in an A.
Related
I was wondering if someone could explain to me how I might be able to implement something similar to this:
namespace advanced_cpp_oop
{
class A
{
B b;
};
class B : public A
{
};
}
int main()
{
}
Where an instance of a base class can contain an instance of a derived class? When the above code is compiled the following error is generated:
g++ advanced_cpp_oop.cpp
advanced_cpp_oop.cpp:8:5: error: ‘B’ does not name a type
The (almost) equivalent Java code which does compile is:
public class AdvancedCppOop
{
public static void main(String[] args)
{
A a;
}
}
class A
{
B b;
}
class B extends A
{
}
Thanks
You need to add a pointer and a forward declaration:
namespace advanced_cpp_oop
{
class B;
class A
{
B* b;
};
class B : public A
{
};
}
In your C++ code, you are creating an instance of your class B inside class A, which is not possible since the compiler does not yet know anything (especially not the size) of class B.
With the code from my answer, you need to dynamically allocate an instance of class B and assign it to the b pointer somewhere else in your code.
On a side note, from design perspective, this does not really make sense since a parent class should not depend on a sub class.
You have to do it with some type of pointer, such as unique_ptr, and a forward declaration:
class B;
class A
{
std::unique_ptr<B> b;
};
class B : public A
{
};
This is silly though and you should probably rethink your design.
There is one very important difference between C++ and Java. C++ is a language with value semantics, while Java is a language with reference semantics. When in Java you create a variable of anything other than a primitive type, you are not creating an object of that type, but a reference to such an object. On the contrary, in C++ the same construct refers to an actual object.
If you keep this in mind, it is simple to understand why the following cannot possibly work:
class Base {
Derived d;
};
class Derived : Base {};
The first definition in C++ means that the object Base contains internally (not by reference) an object of type Derived. At the same time, Derived contains by means of inheritance a subobject of type Base.
That means that Derived contains a Base that contains a Derived containing a Base...
What would be the size of Base or Derived?
In a language with reference semantics, or in C++ if you use pointers, that is not a problem. The Base object contains a reference/pointer to Derived. Derived contains a Base subobject by means of inheritance. The size of Base is well known: all the other fields plus the size of a reference/pointer. The size of Derived is whatever the size of Base is plus any extra members that are added.
Andreas beat me to the correct answer, but I'll just add that the Java code works only because Java objects are implicitly held by pointers (hence the B b = new B(...); statements sprinkled throughout Java code) even if it doesn't look like it. Your original C++ code doesn't work (even with a forward declaration of class B added) because the compiler doesn't know how big a B object is, and thus doesn't know how big an A object that contains it will be. On the other hand, all pointers have the same size (regardless of pointed-to type), so the compiler has no such problems when you replace a B object with a pointer to a B object in class A.
The following simple example will produce a compiler error, since I accidently use private inheritance:
main.cpp:21: error: ‘A’ is an inaccessible base of ‘B’
class A
{
};
class B : /*ups forgot that -> public*/ A
{
};
int main(int , char *[])
{
A* test = new B;
return 0;
}
Could you help me and explain what exactly is inaccessible in the base class and why it is needed in the conversion from B* to A*?
Private inheritance means that for everyone except B (and B's friends), B is not derived from A.
Could you help me and explain what exactly is inaccessible in the base class and why it is needed in the conversion from B* to A*?
Ouside of B and the friends of B, the simple fact that B is an A is not visible. This is not hiding a member variable or member function, but hiding the relationship itself. That is why from main you cannot bind the result of new B with a pointer to A, because as far as main is concerned, B is not an A (in the same way that you could not do A * p = new unrelated;)
As to why it is needed, the answer it exactly the same: because without access to the relationship, the compiler does not know (well, it knows, but will not tell you) how to obtain a pointer to the A subject inside B, because as far as it can see within that context there is no relationship between A and B at all.
The conversion from B* to A* is inaccessible, because the base-class subobject is private. When you convert B* to A*, you return the pointer to the base-class subobject. The latter must be accessible for the conversion to be accessible. In any function that is friend to B the conversion becomes accessible. By the way, you can always access the conversion by an explicit cast.
A* p = (A*)(new B);
Note that in some cases just accessible conversion is required, but in some cases it is required that A be a public (stronger than accessible) base of B. For example, when you try to catch an exception of type B with catch(A&) - it is required that A be a public base class of B.
Since the reference or pointer of Base class can not point to object of inherited class, does it mean that protected and private inheritance is nothing to do with polymorphism?
Since B is inherited from A, the default constructor of A would be called before the constructor of B. But because it is private and not inherited to B, you get a compiler error.
Public/private inheritance is equivalent to public/private member variable.
The result of the conversion is a reference to the base class subobject of the derived class object.
I think the accessibility means the accessibility of the base class subobject of the derived class object.For client,only if we ues public inheritance,the base class subobject is accessible.For the member function of derived class,no matter we use public/protected/privaye inheritance, the base class subobject is accessible.
class A{
};
class B: private A{
private:
int* m_pb;
public:
B(){m_pb=new int(10)};
void func()
{
A* pa= new B; //OK
int *pmb = m_pb; //OK
}
};
int main()
{
B* pb = new B;
A* pa= pb; // inaccessible
int *pmb = pb->m_pb; // inaccessible
}
OK.I means that public/private inheritance is equivalent to public/private member variable.
reference:
http://pic.dhe.ibm.com/infocenter/ratdevz/v8r5/index.jsp?topic=%2Fcom.ibm.tpf.toolkit.compilers.doc%2Fref%2Flangref_os390%2Fcbclr21011.htm
Say we have a concrete class A, and an abstract class B.
Consider a concrete C, that inherits from both A and B, and implements B:
class C : public A, public B
{
/* implementation of B and specific stuff that belongs to C */
};
Now I define a function which signature is void foo(B* b);
This is my code, I can assume that every pointers to B are both A and B.
In foo's definition, how to get a pointer to A?
A nasty but working trick is to align back pointers like so:
void foo(B* b)
{
A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A));
// now I can use all the stuff from A
}
Keep in mind that C does not have a super type and actually, there are many classes akin to C which only are A and B. Feel free to question both my logic and this sample of design as well but the question is only concerning pointers alignment.
void foo(B* b)
{
//A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A)); // undefined behaviour!!!!
A* a = dynamic_cast<A*>(b);
if (a)
{
// now I can use all the stuff from A
}
else
{
// that was something else, not descended from A
}
}
Forgot to say: in order to make work dynamic cast both A and B should have virtual function(s) or at least virtual destructors. Otherwise there is no legal way to do that type conversion.
Having a huge set of unrelated classes that both derive from A and B is a very strange design. If there's something that makes A and B always be "used together" you could either merge them or introduce a shim class that only derives from them and then only derive from that class:
class Shim : A, B {};
class DerivedX : Shim {};
and in the latter case you just use static_cast to first downcast from A or B to Shim* and then C++ it will implicitly convert the Shim* pointer to the other class.
If you want to use the functionality of both class A and Class B in your function then you should modify the function to receive C pointers:
void foo(C* c);
And in general you are wrong with you assumption that "every B is an A as well". You could create classes derived from you B interface and not derived from Class A, that's why the compiler won't know that in your specific case "every B is an A".
Expanding on sharptooth's answer (and entering it as an answer, because I can't get formatted code into a comment), you can still use the shim:
class Shim : public virtual A, public virtual B {};
Then:
class Derived1 : public Shim, public virtual A, public virtual B1
{
};
class Derived2 : public Shim, public virtual A, public virtual B2
{
};
B1 and B2 must derive virtually from B.
But I suspect that if you always need to implement both A and
B, you should create a single interface with both, either by
inheriting, or coalising both into a single class; your B1 and
B2 would inherit from that. (The solution with
dynamic_cast, of course, is for the case where the derived
class of B may or may not also derived from A.)
I have a class as shown below:
class B;
class A
{
public:
A();
~A();
void createStuff(.......); //??
private:
B *b;
};
The object B contains another of class 'C' which has about 20 class member variables.
I want the user of class A to be able to call the function createStuff(...) with a set of arguments so that I can construct the object C. What is the best way of doing this?
The mechanism for classes to grant access to their private members is called friendship.
With what you have posted it looks like something like this may work:
class B
class A:
{
public:
A();
~A();
void ceateStuff(.......); //??
private:
B *b
}
void A::createStuff(argument1, argument2...)
{
C = new C(argument1, argument2...) //You now have an instance of C with the arguments pass in to createStuff();
}
The variable of type C belongs to class B; it mediates the access to the data in C. Class B has constructors; you will use those to set the variable of class B in order, and it is B's job to ensure that the C is correctly managed.
If you need more control over C, then you have a design problem. Either your class A needs its own variable of class C to control, or class B does not provide the tools you need and needs fixing, or you are misguided in thinking you need access to, and therefore direct control over, the contents of the variable of class C.
The Law of Demeter is a guide in such scenarios; you seem to be wanting to contravene it.
In any case you should look at B class, how it implement initialization of C object, can it be controlled (If can't - you should extend interface of class B and add this functionality)?
If C definition is accesible for A maybe you can use constructor of B in such way:
void A::createStuff( const C& c)
{
b = new B(c);
}
Is it possible to getting rid of error C2243?
class B {};
class D : protected B {};
D d;
B *p = &d; // conversion from 'D *' to 'B &' exists, but is inaccessible
I had this error in my app and at the end I've managed to compile it by making an explicit conversion:
D d;
B *p = (B*)&d;
I can't understand why by making class D inherited protected from B makes the implicit conversion inaccessible.
I tried to avoid explicit conversion by creating a operator B() in class D in order to make the conversion accessible:
class B {};
class D : protected B
{
public:
operator B() {return *this;}
};
But there is no way.
Any other solution to avoid explicit conversion?
If you want to allow conversion, you should be using public inheritance.
Using protected or private inheritance, you are declaring that the fact that the derived type inherits from the base class is a detail that should not be visible from the outside: that's why you are getting that error.
You should regard non-public inheritance only as a form of composition with the added possibility to override methods.
Because protected and private inheritance are not is-a relationship, they are just syntax sugar for composition. Your classes can be rewritten exactly like this, but you lose the convenience of letting the compiler define b for you, and using b members directly instead of referring to it explicitly :
class D
{
protected:
B b;
};
For the second point of your question:
operator B() {return *this;}
This line has to do with B and D. D* and B* are totally different from B and D though they are pointers to them! to cast pointers, you could reinterpret the pointer:
B *p = reinterpret_cast<B*>(&d); // TOTALLY WRONG, although it compiles :)
Don't do the above line! I think you might give us more info of what you are trying to achieve.
Because out of D and Ds children, nobody knows that they are parent-child, so you need to do it explicitly.
Thats what protected inheritance means, only your family(children) will know that you inherit. And you could use it, for example in a children method, there an implicit conversion would be legal.
If you want to have implicit conversion out of your children you need to make it public for everyone to know.
The problem here is that you are trying to do an end run around the information hiding that the protected attribute provides. If you want to access an instance of D as a B, why have you inherited it as protected rather than public?. What you are saying in using protected inheritance is that you wish only instances of D and its descendants to be aware of the B component. You need to look again at what you want to accomplish.
The old C style cast that you are using has none of the subtlety of the newer C++ casts so it gives you code that will compile but the problem is really in the inheritance.
Did you try making operator B() public in class D? In the code you showed, it would be marked protected and still inaccessible. But I would avoid conversion operators in general if possible.
Still, inheriting protected B means you intend to prevent doing B* p = &d. Imagine if B was actually a protected member variable at the top of D. Just like you can't access D.b in that case, you can't access d as a B*, unless you cast it away.
So either inherit B publically, or use your casts. I'd go with inheriting B publically, because inheriting it protected basically says "Don't use me as a B", which you are trying to do anyway.
Because nobody outside knows they are parent-child,you only can perform this action in D's derived class.This is an example(Test in Visual Studio 2013):
class BASE{};
class BASE1 :protected BASE{};
class BASE2 :protected BASE1
{
public:
void func(BASE &a, BASE1 &b){a = b;}
};
void main()
{
BASE a;
BASE1 b;
BASE2 c;
c.func(a, b);;
system("pause");
}