I want to implement a class hierarchy in C++:
- I need interfaces so I can provide multiple implementations.
- I need common methods in all the classes. But I need to be able to override specific methods.
- Constructors all take at least one parameter.
Simplified I have this code:
#include <iostream>
class IClass {
public:
virtual int commonMethod() const = 0;
};
class Class : public virtual IClass {
protected:
int commonValue;
public:
Class(int commonValue) : commonValue(commonValue) {}
virtual int commonMethod() const {
return commonValue;
}
};
class IClassDerived : public virtual IClass {
public:
virtual void specialMethod() = 0;
};
class ClassDerived : public Class, public virtual IClassDerived {
public:
ClassDerived(int commonValue) : Class(commonValue) {}
virtual void specialMethod() {
// do something
}
};
class IClassDerived2 : public virtual IClassDerived {
public:
virtual void specialMethod2() = 0;
};
class ClassDerived2 : public ClassDerived, public virtual IClassDerived2 {
public:
ClassDerived2(int commonValue) : ClassDerived(commonValue) {}
virtual void specialMethod2() {
specialMethod();
}
};
class IClassDerived3 : public virtual IClassDerived2 {
public:
virtual int commonMethod() const override = 0;
};
class ClassDerived3 : public ClassDerived2, public virtual IClassDerived3 {
public:
ClassDerived3(int commonValue) : ClassDerived2(commonValue) {}
virtual int commonMethod() const override {
return 4711;
}
};
int main() {
ClassDerived foo(1);
ClassDerived2 foo2(2);
ClassDerived3 foo3(3);
std::cout << foo.commonMethod() << " " << foo2.commonMethod() << " " << foo3.commonMethod() << " " << std::endl;
// 1 2 4711
return 0;
}
I now have two questions:
- Why does this work at all?
- If I try without virtual inheritance I get errors "‘specialMethod’ is ambiguous" and "... because the following virtual functions are pure within ‘ClassDerived’: virtual int IClass::commonMethod() const". Because of the two base classes every member is there two times which results in these errors. Ok.
- If I do virtual inheritance and specify both base classes with "public virtual" I get "no matching function for call to ‘Class::Class()’". Researching showed me that in case of virtual inheritance I need a default constructor for the base classes.
- By trial-and-error I found the solution above. But I don't understand why it works so far. What happens when only one base class is "virtual" but not the other one?
- Is there a better way? I managed to get this little example to compile but in reality my classes are complexer and I am afraid this only works in this little snippet and I am not seeing future problems this could bring up...