Share instance of base class for indirect base classes possible? - c++

I must admit I'm having trouble formulating this question, but I'll try my best to be precise. I have tried to search for an answer to my question, but I suspect I have been unable to find what I'm looking for, as I'm not exactly sure what to call this.
I have a base class A, and several child classes inheriting from this base class. I then make another class X that inherits from some of the mentioned child classes. The problem I'm now facing is that each of the classes X inherits, have their own instance of class A. The code below should give a better understanding of what I mean.
class A;
class B : public A;
class C : public A;
class X : public B, public C;
Is there a way to make class B and C share the same instance of class A, when they are both acting as indirect base classes for the same class?
To give an example of why I want this, lets look at this code.
class A
{
int _x;
};
class B : public A
{
void outputX(){std::cout << A::_x << std::endl;
};
class C : public A
{
void setX(int x){A::_x=x;}
};
class X : public B, public C
{
C::setX(5);
// this will output an un-initialized _x,
// as B and C have their own version of A
B::outputX()
};
Now I realize this seems rather unnecessary in this example here, but in my real situation I like to think it would be a good solution if B and C shared instance of A in class X.
Is this at all possible?

You can solve this by using virtual inheritance:
class B : virtual public A;
class C : virtual public A;
class X : virtual public B, virtual public C;
See more on the diamond problem.

Related

Upcasting to a C++ class that is a base class in more than one way (without having to use virtual inheritance)

class A { };
class B : public A {};
class C : public A, public B {};
int main()
{
C c;
A *pA = static_cast<A *>(&c);
}
In the above code, class C is derived from class A in two different paths:
1. Directly from A
2. Indirectly through B i.e. A<-B<-C
So, when I cast an object of class C into a pointer to class A, g++ on Linux reports the following error:
error: A is an ambiguous base of C
I have also tried the same code by removing the static cast as follows:
A *pA = &c;
But, I still get exactly the same error.
Is there any solution for this? BTW, the same works fine without error on Windows using Visual C++ compiler.
I know that virtual inheritance solves this but I need a solution to make this work on g++ on Linux without having to use virtual inheritance. Rather than having to use virtual inheritance, is there any way I can instead specify one of the two path and get rid of the ambiguity. Many thanks!
If you can modify C, one possible approach would be to "inject" a dummy base class between it and A:
class A { };
class B : public A {};
class AlmostA : public A {};
class C : public AlmostA, public B {};
int main()
{
C c;
A *pA = static_cast<A*>(static_cast<AlmostA*>(&c));
}
[Live example]
You can even embed the dual static casts into a function in C.
Long story short, inherit from A virtually to avoid having two distinct As being a part of C:
class A { };
class B : virtual public A {};
class C : virtual public A, public B {};
Now your code will compile and run correctly.
Unlike "regular" base classes, virtual base classes are inherited only once, regardless of the number of paths that have them. Read this Q&A for a detailed explanation of how they work.

base class ambiguous when converting derived class pointer to base class

I'm using C++. When I try to convert a derived class' pointer to base class', compiler complains "base class is ambiguous".
I did some research, and found this question How can I avoid the Diamond of Death when using multiple inheritance?. And some other similar issue.
There is a solution, is to use virtual inheritance. But I'm not able to change class definitions, because they are compiled libraries.
Is that possible to do the converting, without changing base class definitions?
A minimal sample would be:
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
What I want to do is:
D *d = new D;
A *a = (D *)d; // ambiguous
Is that possible to do the converting, without changing base class definitions?
Yes it is. You have to choose which direct base class to go through.
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
void foo(A&) {}
int main() {
D d;
foo(static_cast<B&>(d));
foo(static_cast<C&>(d));
return 0;
}
I found a way to do this converting, a little tricky though.
Following code would do the job:
A *a = (B *)d;

Understanding how to solve ambiguous member requests in c++

How do I use a function in class A from class D without inheriting class A and (although I understand it's bad practise, I am not permitted to alter the inheritance at all) and not remove the inheritance from C and B in D? I cannot seem to find a way around the request for member is ambiguous error. I was (wrongly) of the understanding that no matter how far removed the
class A
{
public:
void DoEverything(int){ }
};
class B : public A
{
public:
...
};
class C : public A
{
public:
...
};
class D : public C : public B
{
public:
...
};
int main()
{
D dMan;
int i = 2;
dMan.DoEverything(i);
}
My example is loosely based on the "Ambiguous base classes (C++ only)" example found here: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr138.htm#cplr138 but that hasn't helped me understand the problem.
First of all, to make it work just do the following changes
class B : virtual public A
...
class C : virtual public A
This problem in multiple inheritance is called the diamond problem. Check out this link to know more
http://www.cprogramming.com/tutorial/virtual_inheritance.html

Multiple inheritance. How to access member function of 1 Parent class to another parent class

I have class C and it is inheriting from Class A and Class B.
Is it possible for class A to access Class B function( eg fun1() ) using this inheritance. A and B are both independent class and fun1() is only in class B.
Not strictly through inheritance. Although A and B are parents of C, A and B have no relationship and no way to access eachother.
It is possible through inheritance and polimorphism, then class A have a virtual method that C implements calling the function in B, like this:
class A {
public:
b get_b() { return do_get_b(); }
private:
virtual do_get_b() = 0;
};
class B {
public:
b some_b;
};
class C : public A, public B {
private:
virtual do_get_b() {return some_b;}
}
You could check with dynamic_cast to see if your object of A is really a object of C, and thereby of B
void A::foo()
{
B* pB = dynamic_cast<B*>(this);
if (pB) pB->bar();
}
But if A and B are really independent of one another it is probably better to find a different solution.
Sometimes, it is possible. An example how to achieve this.
That example applies to a diamond hierarchy, which is a bit more complicated than yours. In your terms, ClassA and ClassB should be derived from class Base, ClassC is derived from ClassA and ClassB.

Making the parent private and the grandparent public for a class

Short story:
is it possible to do
class A{};
class B:public virtual A{};
class C:public virtual A,private B{};
i.e. "showing" that C is an A and not a B, but making it actually a B
without adding the virtual (and the corresponding vptrs)?
Long story:
A has several methods.
B adds some more.
Sometimes I want to forbid the use of one of them. C has this purpose.
The program has many B, few Cs. I do not want then to make B a subclass of C.
Yes, this will do exactly what you intend it to do.
But consider another option: inheriting publicly and hiding the unwanted methods:
class A
{
public:
int a() {return 0xaa;}
};
class B: public A
{
public:
int b() {return 0xbb;}
};
class C: public B
{
private:
using B::b; // makes the method called b private
};
...
B().b(); // OK, using method b in class B
C().b(); // error: b is private in class C
C().B::b(); // OK: calling b in base-class (not sure if you want to prevent this)
This will work with both virtual and non-virtual inheritance.