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).
Related
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.
I have three classes named A, B, and C. B inherits from A and C inherits from B. (A -> B -> C).
I also have an abstract base class named IBinary. I'd like to make all of the classes implement the IBinary interface. When I make class A inherit from IBinary, the output of my code is C::readb. When class A does not inherit from IBinary, the output is B:readb.
What is the proper way to make my three classes subscribe to the same interface? If I only have the top class (A) inherit from the interface class, I'll need to refactor my code so that I don't have resolution problems like the one above.
If I explicitly have all of the classes inherit from the interface class then I'll have a more complicated class hierarchy and become closer to having a diamond of death.
#include <iostream>
class IBinary {
public:
virtual void readb( std::istream& in ) = 0;
};
// Basic A -- change whether this inherits from IBinary
class A : public IBinary {
public:
A() {};
void readb( std::istream& in ) {}
};
// Specialized A
class B : public A {
public:
B() {};
void load() {
this->readb(std::cin); // <-- which readb is called?
}
void readb( std::istream& in ) {
std::cout << "B::readb" << std::endl;
}
};
// Specialized B
class C : public B {
public:
C() {};
void readb( std::istream& in ) {
std::cout << "C::readb" << std::endl;
}
void foo() {
B::load();
}
};
int main() {
C c;
c.foo();
}
The virtual in the definition of IBinary::readb makes all the difference.
When you inherit from IBinary, all the readbs in the hierarchy that override the one from IBinary are implicitly virtual, too. So virtual dispacth kicks in, just as it's supposed to.
When you don't, then the call is resolved statically. Because the call is inside B, it is B::readb that gets called.
Just have A inherit from IBinary which will make all the children be usable as the abstract interface IBinary.
The reason you are seeing this behavior is, in short, because A::readb is not declared virtual.
Because IBinary::readb is virtual, when A inherits from it, A::readb becomes virtual by default.
Your code would behave more consistently if you added virtual to every declaration of readb, rather than just the first. For this reason, a lot of code style guides for C++ make it a requirement that all virtual methods be declared virtual in all derived classes, even if they are not the ancestor base class.
Yesterday, I wrote some code and i would really appreciate a judgement if this is good or bad practice. And if its bad, what could go wrong.
The construct is as followed:
The base class A comes from an API sadly as a template. The goal was to be able to put derived classes from A in a std::vector. I achieved this with the base class B from which all derived classes that inherit from A will inherit. Without the pure-virtual function in B the foo() function from A was called.
With the pure-virtual function in B the foo() version from C get called. This is exactly what I want.
So is this bad practice?
EDIT:
To clear some misunderstandings in my example code out:
template <class T>
class A
{
public:
/* ctor & dtor & ... */
T& getDerived() { return *static_cast<T*>(this); }
void bar()
{
getDerived().foo(); // say whatever derived class T will say
foo(); // say chicken
}
void foo() { std::cout << "and chicken" << std::endl; }
};
class B : public A<B>
{
public:
/* ctor & dtor */
virtual void foo() = 0; // pure-virtual
};
class C : public B
{
public:
/* ctor & dtor */
virtual void foo() { std::cout << "cow"; }
};
class D : public B
{
public:
/* ctor & dtor */
virtual void foo() { std::cout << "bull"; }
};
The std::vector shall contain both, C as well as D and
void main()
{
std::vector<B*> _cows;
_cows.push_back((B*)new C()));
_cows.push_back((B*)new D()));
for(std::vector<B*>::size_type i = 0; i != _cows.size(); ++i)
_cows[i].bar();
}
with output
cow and chicken
bull and chicken
is desired.
As far as I know is there no other way to store classes derived from a template class in a container than the use of a base class. If I use a base class for my derived classes, e.g., B i must cast every instance within the vector back to its proper class. But at the time bar() is called, I don't know the exact type.
I call it bad practice for doing possibly confusing and obfuscating things.
1) A function name should in all base and sub-classes either be virtual or non-virtual.
mixing overriding and overloading within the inheritance hierachry is a very bad idea.
No one really expects something like that.
Thus if A::foo should be virtual as well, or B and C foo should not.
2) Preferably base classes should be interfaces.
As such A:foo should be pure virtual and not B::foo.
2b) If a base class has already provided a default implementation don't declare the function pure virtual in a sub-class.
Suppose I have this class hierarchy:
class A {
public:
virtual void foo(Base *b) = 0;
};
class B {
public:
virtual void bar() = 0;
};
class C : public A, public B {
public:
virtual void viz() = 0;
};
class E : public C {
public:
/** Some non-pure virtual functions, does not implement foo */
};
class F : public E {
/** does not implement foo */
}
class G : public E {
/** does not implement foo */
}
Now, I would like to define derived, "templatized" versions of F and G, which declares a method foo(T *s) and where the implementation of foo(Base *s) simply calls foo(T *s) by applying a static_cast.
Moreover, I don't wan to expose the template arguments to A, because users of these interfaces (A, B, C, E) should not be exposed to the template parameters (I'm writing a plugin architecture and user-types that derives a given interface are passed back and forth from plugins to base system).
What I thought was to define this class:
template <typename T>
class GA : public A{
...
}
and to define the "templatized" derivations of F and G like this:
template <typename T>
class GF : public F, public GA {
...
}
the problem is that GF sees two different declarations of foo() (one given by A, the other by GA), so the compiler throws me an error when I try to instantiate GF because foo(Base) is not defined.
How can I solve this?
Why do you need multiple inheritance? Why not just class C : public Impl { ... }?
I think the problem is that Impl inherits class A and class C inherits both Impl and A. This means there will be two instances of class A where first A's foo is implemented by Impl and a seconds one is still pure virtual. Virtual inheritance can solve this problem, for example:
class A {
public:
virtual void foo () = 0;
};
class Impl : virtual public A {
public:
virtual void foo () {}
};
class C
: virtual public A
, public Impl
{
};
I would suggest something different. Declare the function as a pure virtual function, and then just trivially implement it in the derived classes by forwarding the call:
class A {
public:
virtual void foo() = 0;
};
void A::foo() {}
class B : public A {
void foo() { A::foo(); }
};
But that does not mean that you cannot achieve what you are trying to do. If you want to implement that operation in another class and use inheritance, you can do it in two different ways:
Intermediate type:
Implement an intermediate type that provides the functionality, then each derived type can extend either the original A or the intermediate I type:
class I : public A {
public:
void foo() {}
};
class B : public I {}; // inherits the implementation
class C : public A { // needs to provide it's own implementation
void foo() {}
};
Virtual inheritance:
Alternatively you can use virtual inheritance (of the three options I would avoid this). In this way you can create a hierarchy where V inherits virtually from A and provides the implementation. The rest of the classes can either inherit from A directly or inherit from A virtually and also inherit from V. By using virtual inheritance you ensure that there is a single A subobject in your hierarchy:
class V : public virtual A {
public:
void foo() {}
};
class B : public virtual A, V { // Inheritance from V is a detail, can be private
// no need to provide foo
};
Note that this approach is overkill for this particular limited problem, and that it has side effects (the layout of the objects will be different and they will be slightly bigger in size). Again, unless you want to mix and match functions from different sibling classes, I would avoid this.
What was wrong in your code
The problem in your code is that you are inheriting from A multiple times, one through D and another directly. While in the path from D the virtual function is no longer pure, in the direct path from A the virtual function is still undefined.
That also causes the second issue in the error message: ambiguity. Because there are two A subobjects, when you try to call foo on the most derived type, the compiler cannot figure out on which of the two A subobjects you want to execute the request. The same type of ambiguity problems would arise if you tried to cast from the most derived type into A directly, as the compiler would not know to which A you want to refer.
Impl does not implement A's method in D and C, it's a completely different base.
You should derive Impl from A, then derive every class of that subset from Impl instead of A.
If you want to inherit from both the A and Impl, then you need to use virtual inheritance.
Edit:
See #Vlad's answer for more details.
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();
}
}