struct Base
{
virtual ~Base() = default;
virtual Base *f() const = 0;
};
struct A
: virtual Base
{
virtual A *f() const override = 0;
};
struct B
: virtual Base
{
virtual B *f() const override = 0;
};
struct Middle
: virtual A
, virtual B
{
};
struct Derived
: Middle
{
virtual Derived *f() const override = 0;
};
main.cpp:19:8: error: virtual function 'Base::f' has more than one final overrider in 'Middle'
struct Middle
^
main.cpp:5:19: note: overridden virtual function is here
virtual Base *f() const = 0;
^
main.cpp:11:16: note: final overrider of 'Base::f' in 'A'
virtual A *f() const override = 0;
^
main.cpp:16:16: note: final overrider of 'Base::f' in 'B'
virtual B *f() const override = 0;
^
I don't understand why this error even exists, all the member functions are pure virtual. Middle is actually a template in my code and I can't change it to accommodate for specific cases.
EDIT: I can work around it by just not declaring f() in A or B (it's private anyway) but I would still like to know why this doesn't work.
struct Base
{
virtual ~Base() = default;
virtual Base *f() = 0;
};
struct A : virtual Base
{
virtual Base *f() override
{
returndynamic_cast<A*>(this);
}
};
struct B : virtual Base
{
virtual Base *f() override
{
returndynamic_cast<B*>(this);
}
};
struct Middle : A , B
{
virtual Base *f() override
{
returndynamic_cast<Middle*>(this);
}
};
struct Derived : Middle
{
virtual Base *f() override
{
returndynamic_cast<Derived*>(this);
}
};
int main()
{
// test
Base* a = new A;
Base* b = new B;
Base* c = a->f();
Base* d = b->f();
Base* e = new Middle;
Base* f = e->f();
// final test
//get the real object
Base* g = new Derived;
Derived* h = dynamic_cast<Derived*>(g->f());
delete a;
delete b;
delete e;
delete g;
return 0;
}
edit:
also note that you don't have to virtually inherit A and B in Middle class.
Then, any program using Middle would be ill-formed.
1 2 3 4 5 6
struct Middle : virtual A , virtual B
{
// there is only one Base sub-object in Middle
// and Miidle has two final overriders of Base::f()
// A::f() and B::f()
};
In a derived class, if a virtual member function of a base class subobject has more than one final overrider the program is ill-formed. - IS
> but I was hoping more to learn the reasoning behind it.
My guess is that special-casing for all pure virtuals to allow such a construct would place a needless burden on implementations; without giving even a fractionally commensurate benefit to programmers.
It's pretty convoluted and requires extra effort on the user's part, is there a better way of doing it? Ideally the user should just need to provide a class that extends all of the other specified classes and overrides the conflicting member functions as pure virtual.
Note: Middle is huge and has a lot of guts and internals, I can't specialize it without massive code duplication.
> the user should just need to provide a class that extends all of the other specified classes
> and overrides the conflicting member functions as pure virtual.
Ideally, the user should not be required to override a pure virtual as a pure virtual.
Basically: if you have an implementation, give it; otherwise do nothing.
I should have specified, the return type for f() in my example should be ignored - it does change in each class but it is not the same as the class it is in. It actually follows a completely different class hierarchy that I omitted for simplicity.