C++ - OOP design - multiple inheritance and pure virtual method [duplicate] - c++

This question already has an answer here:
abstract base classes, multiple inheritence, and common pure virtual methods
(1 answer)
Closed 6 years ago.
I have this problem, that I dont know, how to solve correctly.
class A : public B, public C
{
virtual void GetSomethingElse()
{
}
}
class B
{
public void GetSomething()
{
GetSomethingElse();
}
virtual void GetSomethingElse() = 0;
}
class C
{
virtual void GetSomethingElse() = 0;
}
Basically, what I have are two abstract classes B, C. Usually, I just need to inherit one of them, but in some particular cases, I need both of them.
How to correctly solve this problem with GetSomethingElse() method, that needs to be called from B. If I inherit only B, it will be implementted in child. If only from C, all is still OK.
However, if I inherit B and C, I have some "weird" design, that resemlbes diamond inheritance problem, but it is quite not the same.

As you already mentioned it is quite different from diamond problem.
Your design is correct and not weired. Having GetSomeThingElse as pure virtual is to enforce the child to define it. Defining it if it is because of C or B is not a design issue.
You would have a design issue if it were pure virtual in one and virtual in the other (B or C) as one gives you the choice and the other by obligation.

class A : public B, public C
{
virtual void GetSomethingElse()
{
}
}
class B:public class D
{
public void GetSomething()
{
GetSomethingElse();
}
virtual void GetSomethingElse()
{
}
}
class C:public class D
{
virtual void GetSomethingElse()
{
}
}
//here's the only pure virtual base class
class D
{
virtual void GetSomethingElse() = 0;
}

As they are abstract, you need to overwrite the method in class A.
Each object will know if it is a B or a C, so it will call the right function.
if, however, your class C has no function GetSomething(), then your inheritance structure is the wrong way around - remember the logic of inheritance is that every object of a derived class is an object of the parent class too? So if an A is not a B because is doesn't have such a call, something is wrong.
Another point is to derive virtual, so the two identical functions are considered the same: class A : virtual public B, virtual public C
Did you consider making a class that is the parent of B and C? If they don't have a common parent, why do they have a function each with the same name?

Related

Calling appropriate parent class function from derived class function in multiple inheritance

Suppose I have the following classes:
class Base {
virtual void func() { cout << "func base" << endl; }
};
class A : virtual public Base {
public:
virtual void func() { cout << "func A" << endl; }
};
class B : virtual public Base {
public:
virtual void func() { cout << "func B" << endl; }
};
class C : public A, public B {
C(bool is_a);
public:
virtual void func() { // Call appropriate parent's func here }
};
My requirement is that the appropriate parent class' function func() be called when I call C's func(). This is what I mean by appropriate:
Base* ptr = new C(true /*is_a*/);
ptr->func(); // This should call A's func internally
How to achieve this? Is it even possible?
[edit]
This might be more of a design question. It is known that class C will have only one true parent (either A or B). And depending on which is the parent, I want that function to be called. Any alternative design suggestions are welcome.
I am deriving C from A and B because there is some common functionality which both A and B share and which can't be a part of base class.
You need to call A::func() explicitly.
class C : public A, public B {
public:
virtual void func() { A::func(); }
};
Update (to yours):
What do you really want to achieve? Is there an actual problem that you want to solve?
If you know that "class C will have only one true parent", why do you need to derive from A and B in the first place? Even though Aconcagua's answer works, it looks more like a workaround for a problem that isn't properly stated from your side. In case you are dealing with different implementations for your class, wouldn't you want to employ some kind of pattern (like the bridge or strategy pattern) instead?
This might be more of a design question. It is known that class C will have only one true parent (either A or B). And depending on which is the parent, I want that function to be called. Any alternative design suggestions are welcome.
class Base { };
class A : public Base { };
class B : public Base { };
class C
{
// common interface for all types of C
};
class C_A : public A, public C { };
class C_B : public B, public C { };
Now you can use C_A, wherever a C needs to behave as A and C_B analogously...
In above example, all virtual inheritances are removed, they are not needed as is. Depending on the use case, it might or might not be appropriate to let class C itself inherit from Base. If so, let all of A, B and C inherit virtually from Base. C_A and C_B, though, do not need to inherit virtually from their parents (there still will just be one Base instance inherited due to the virtual inheritance of the base classes).

Two folded polymorphism is weird, how to make it extensible?

For example, I have an abstract base class A and B. A has a virtual method as follows
class A
{
public:
virutal void f(B& b) = 0;
};
For class A1
class A1 : public A
{
public:
void f(B& b) override { b.f(A1); }
};
And thus for B, it needs a virtual method f(A1)
class B
{
public:
virtual void f(A1& a) = 0;
};
And in class B1 : public B, the virtual method is implemented. The problem is that when another class A2 : public A is added, I have to add a virtual method virtual void f(A2& a) = 0 in class B, which I think it breaks the code because I don't know if A2 even A1 is added or not when I design class B. How to avoid it but implement the equivalent requirements? Any C++ feature can be used even with templates.
Unfortunately, there's no such thing as a virtual template function in C++ (this is what I believe you're trying to accomplish, after parsing your question).
The closest, and the least ugly solution I can think of, is to have the virtual function in base class B take the base class A as a parameter:
class B
{
public:
virtual void f(A& a) = 0;
};
B1 overrides that, and then uses dynamic_cast to cast its parameter to an instance of A1.
In this manner, you can continue an define each Ax and Bx pair of derived classes, without having to change the API interface in the base class, between the two hierarchies.
A bit ugly, but the question states "any C++ feature can be used", and dynamic_cast certainly qualifies under that requirement.

Stop propagation of a virtual method in child class

I have a main class, "A", and two child class "B" and "C", with some methods
Class A
{
virtual bool method1() const = 0;
virtual void method2(int) = 0;
}
Class B : public A
{
bool method1() const;
}
Class C : public A
{
void method2(int);
}
But when i try to declare a new B object, my compiler say me "cannot instantiate abstract class, pure virtual function A::method2 has nos overrider". Is there a way to fix that ?
By putting = 0 at the end of a virtual method declaration you are making it pure virtual. Thus you are telling the compiler that no implementation is provided in the base class and that any derived classes must provide one. Since your derived class B doesn't implement method2 you get that error message. The compiler is doing exactly what you told it to.
If you don't actually want to force all derived classes to implement a virtual function, then you shouldn't make is pure virtual. So you would remove the = 0 and provide some kind of default implementation in the base class. Depending on your design, this could as simple as virtual void method2(int) { }
Otherwise, the derived classes must implement all pure virtual methods. So in the code you've posted, B and C each need to implement both method1 and method2.

Define the method once to be virtual in the inheritance hierarchy to make polymorphism to work

Is it sufficient to define the method once to be virtual in the inheritance hierarchy to make polymorphism to work.
In the following example Der::f is not defined to be virtual but d2->f(); prints der2
I am using VS IDE (may be it is only there...)
class Base
{
public:
virtual void f() { std::cout << "base"; }
};
class Der : public Base
{
public:
void f() { std::cout << "der"; } //should be virtual?
};
class Der2 : public Der
{
public:
void f() { std::cout << "der2"; }
};
int main()
{
Der* d2 = new Der2();
d2->f();
}
Yes, polymorphism will work if you define method as a virtual only in your Base class. However, it is a convention I came across working with some large projects to always repeat virtual keyword in method declarations in derived classes. It may be useful when you are working with a lot of files with complex class hierarchy (many inheritance levels), where classes are declared in separate files. That way you don't have to check which method is virtual by looking for base class declaration while adding another derived class.
Everything that inherits from Base - directly or through several layers will have f() virtual as if the class declarion had explicitely placed virtual when f() was declared.

Inheriting both abstract class and class implementation in C++

I hope this is a simple question.
Can I inherit both an abstract class and it's implementation? That is, can the following be made to work?
class A {
virtual void func1() = 0;
}
class B {
void func1() { /* implementation here */ }
}
class C : public A, public B {
}
I've tried a few variations, and am getting compile errors complaining about unimplemented methods in class C. I can save a lot of repeated code if I can make this work, however. Is it possible?
I solved this by creating a "composite class" called D which inherits from A & B, but contains the implementation code previously contained in B. This makes my inheritance model less clean, but it solves the problem without requiring code duplication. And, as I noted in the comments below, it makes my naming conventions pretty gross.
class A {
virtual void func1() = 0;
}
class B {
// Other stuff
}
class D : public A, public B {
void func1() { /* implementation here */ }
}
class C : public D {
}
class B is not an implementation of class A in your code. Class B should be inherited from class A and func1 should be virtual. Only in that case class B will be implementation of class A. And then there is no need to inherit from both A and B.
class A {
virtual void func1() = 0;
}
class B : public A {
virtual void func1() { /* implementation is here */ }
}
class C : public B {
}
Otherwise you will get unimplemented pure virtual function func1.
Make B inherit from A. If that is not possible, using virtual inheritance might also work (I am not entirely sure about this).
If you want to reuse code from B class in C class, try to do something like this:
class C : public A, public B {
void func1(){ B::func1(); }
}
As Kirill pointed out: Your premise is wrong.
Class B in your example does not inherit class A (it needs to be declared to do that first).
Thus, B.func1() is something entirely different to A.func1() for the compiler. In class C it is expecting you to provide an implementation of A.func1()
Somebody above posted something along the lines of:
class C : public A, public B
{
// implement A::func1()
virtual void func1()
{
// delegate to inherited func1() in class B
B::func1();
}
}