I see this problem in C++.
class A{
public:
char* getName(){ return "A";}
void showData(){
cout<<"A";
}
};
class B:public A{
public:
void showData(){
A::showData();
cout<<"B";
}
};
class C:public A{
public:
void ShowData(){
A::showData();
cout<<"C";
}
};
class D:public B,public C{
public:
void showData(){
B::showData();
C::showData();
cout<<"D";
}
};
Problem1:
D* d=new D();
d->showData(); // I want it prints "ABCD" but it prints "ABACD"
Problem2:
cout<< d->getName(); // it shows error: ambiguous access of 'getName'
Can you help me solve 2 problems?
Thanks.
Problem 2 is happening because your class D contains two copies of the base class A. When you call d->getName(), the compiler does not know which one to pick up. To fix this, use virtual inheritance.
Simply put, derive your class A virtually in both classes B and C:
class A { ... }
class B : public virtual A { ... }
class C : public virtual A { ... }
class D : public B, public C { ... }
This guarantees a single embedded copy of class A in class D and will solve the ambiguous access error.
As for problem 1, virtual inheritance will be a good start, but you will need to find some way to rework your logic so that A::getName() is not called twice when you call D::getName().
Related
I have written a C++ program.
#include <iostream>
#include <string>
using namespace std;
class A
{
int a;
public:
void read()
{
cin>>a;
}
};
class B:public A
{
public:
B()
{ }
};
class C:public A
{
public:
C()
{}
};
class D:public B,public C
{
public:
void display()
{
cout<<a<<endl;
}
};
void main()
{
A a1;B b1;C c1;
D d1;
d1.display();
}
I get a message saying there is ambiguity. B is inheriting A.. So B class would inherit item 'a' from class A. Also, C class will inherit item 'a' from class A. Now if im trying to inherit both B and C classes in class D, which item 'a' will i be able to access ?? from class B or from class C ?? Is there any way where i can remove the ambiguity .?
You can fix your ambiguity problem by using one of the following options:
Be explicit about the base class
Use B as the explicit base class
void display()
{
cout<< B::a <<endl;
}
or use C as the explicit base class.
void display()
{
cout<< C::a <<endl;
}
Use virtual inheritance
Change B and C to use virtual inheritance.
class B: virtual public A
{
public:
B() {}
};
class C: virtual public A
{
public:
C() {}
};
Consider the following example:
class A{
public: virtual void hello() = 0;
};
class B: public A{};
class C {
public: void hello(){
cout<<"Hi";
}
};
class D: public B, public C{};
The idea is that I would like to inject the implementation of hello into D through C. This doesn't seem to work unless I make C inherit from A too. Since that leads to diamond inheritance, I end up using virtual inheritance.
Is there any alternative to forcing an implementation into a derived class, without disturbing the abstract classes A and B here?
EDIT: I want a solution where I don't need to explicitly write code within D. This is because, I have many classes like D having the same implementation, which is exactly why I would like to push that implementation up to some class from which all of them inherit.
You can rewrite C as a template class that inherits from it's template argument and then derive D from C.
template <class Base>
class C : public Base {
public: void hello(){
cout<<"Hi";
}
};
class D: public C<B> {};
You can consider static inheritance/ policy classes when you need to inject an outside method into a class hierarchy. Note that injecting the method usually means that the method does not have the same name as an existing virtual in the class hierarchy (if it does, you are forced to use virtual inheritance or explicitly call with the scope :: or insert it in the class hierarchy). I called the method externalHello here.
The other options work fine as well but they conceptually point more to the fact that the injected method is not really an abstract method that could be used outside of this class hierarchy but should have been part of it in the first place.
class A
{
public:
virtual void hello() = 0;
};
class B: public A
{
public:
void hello()
{
cout<<"Hi from B" << endl;
};
};
template<typename T> class C1
{
public:
void injectedMethodUnrelatedToClassHierarchy()
{
cout<<"Hi from C1 with unrelated method" << endl;
};
void externalHello()
{
static_cast<T*>(this)->hello(); // will still call hello in B
injectedMethodUnrelatedToClassHierarchy(); // this will call hello here
};
};
class D: public B, public C1<D>{};
With client code:
D dx;
dx.hello();
dx.externalHello();
dx.injectedMethodUnrelatedToClassHierarchy();
It may work
#include<iostream>
using namespace std;
class A
{
public:
virtual void hello() = 0;
};
class C {
public: void hello(){
cout<<"Hi\n";
}
};
template<typename T>
class B: public A, public T
{
public:
void hello() override{ //override A::hello()
//do other staff
T::hello(); // call C::hello()
}
};
class D: public B<C>{
};
int main()
{
D d;
d.hello();
return 0;
}
This is a code fro diamond tree problem of multiple inheritance
and according to me this code is cool but it is showing some error on compilation
..help me to figure the error
#include<iostream>
using namespace std;
class A //A Diamond tree problem
{
int x;
public:
A(int i) { x = i; }
void print() { cout << x; }
};
class B: virtual public A
{
public:
B():A(10) { }
};
class C: virtual public A
{
public:
C():A(20) { }
};
class D: public B, public C{
};
int main()
{
D d;
d.print();
return 0;
}
It would be useful to see the error:
In constructor ‘D::D()’:
error: no matching function for call to ‘A::A()’
When using virtual inheritance, the virtual base class must be initialised by the most derived class. In this case, that is D; so in order to be able to instantiate D, it must initialise A:
class D: public B, public C
{
public:
D():A(42) {}
};
Alternatively, you could provide A with a default constructor. Declaring any constructor will prevent the compiler from implicitly generating one for you.
You need to provide default construct for D and call A in member initialize list:
class D: public B, public C{
public:
D():A(30){}
};
Or you could provide a default A constructor
A():x(0) {}
Here is a skeleton code:
class C{
callMe(){}
};
class A{
// How to use callMe()
};
class B : C {
callMe();
A a;
};
In this example class B extends class C, so it can call callMe() method. But I need to use callMe() using class A given that class A can not extend class C. I wonder how?
you need to make A contain an object of type C.
class A
{
private:
C objC;
public:
void WhateverMethod() { objC.CallMe(); }
};
Also, the syntax for inheritance is
class B : C{
};
If you want B to simply have access to CallMe(), then you do not need to redefine it in B. It will inherit it from C. If you want B to override CallMe then you need to do this:
class C
{
public:
virtual void CallMe() { //definition }
};
class B : public C
{
public:
void CallMe() { //redefine it here }
};
Note, I assume from your syntax errors that you are a JAVA programmer. Methods are not automatically marked as virtual in C++, you have to mark them as virtual if you want to use polymorphism, and you have to use them from a pointer for it to work.
class C{
callMe(){}
friend class A;
};
class A{
//use call me here
};
You need to provide an instance of C:
class C {
public: // has to be public
void callMe() const {}
};
class A{
public:
A(const C& inst) : inst(inst) {}
void foo() {
inst.callMe();
}
private:
const C& inst;
};
In my class design I ran into the following problem:
class MyData
{
int foo;
};
class AbstraktA
{
public:
virtual void A() = 0;
};
class AbstraktB : public AbstraktA
{
public:
virtual void B() = 0;
};
template<class T>
class ImplA : public AbstraktA
{
public:
void A(){ cout << "ImplA A()"; }
};
class ImplB : public ImplA<MyData>, public AbstraktB
{
public:
void B(){ cout << "ImplB B()"; }
};
void TestAbstrakt()
{
AbstraktB *b = (AbstraktB *) new ImplB;
b->A();
b->B();
};
The problem with the code above is that the compiler will complain that AbstraktA::A() is not defined.
Interface A is shared by multiple objects. But the implementation of A is dependent on the template argument. Interface B is the seen by the outside world, and needs to be abstrakt.
The reason I would like this is that it would allow me to define object C like this:
Define the interface C inheriting from abstrakt A.
Define the implementation of C using a different datatype for template A.
I hope I'm clear. Is there any way to do this, or do I need to rethink my design?
You have two paths of inheritance from AbstracktA, you implement AbstraktA::A() only in one of them, so the compiler complains.
You probably want to inherit virtually from AbstraktA in both case so that there is only one AbstraktA base object (add virtual before AbstraktA).
I forgot to add virtual destructors to the base classes. This leads to runtime malloc errors I believe.
AbstraktB *b = new ImplB;
b->A();
b->B();
delete b;
In debug mode, at the delete statement, GCC gives me:
malloc: *** error for object 0x60e2c4: pointer being freed was not allocated
I solved this by changing the base classes to:
class AbstraktA
{
public:
virtual ~AbstraktA(){};
virtual void A() = 0;
};
class AbstraktB : virtual public AbstraktA
{
public:
virtual ~AbstraktB(){};
virtual void B() = 0;
};