Reputation: 1
I have the following code:
struct A{ f()=0; };
struct Aa : A{ f(){} };
struct B{
void foo(A&)=0;
};
struct Bb : B{
void foo(Aa&);
};
Right now I can't create a Bb
class instance since I didn't override foo
from class B
with demanded parameter. How can I make it work?
Upvotes: 0
Views: 249
Reputation: 10021
From [class.virtual]/2
(C++17 N4713)
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (11.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides112 Base::vf. For convenience we say that any virtual function overrides itself.
Now, in this case, the note 112 is actually important.
- A function with the same name but a different parameter list (Clause 16) as a virtual function is not necessarily virtual and does not override.
In your case, you have the same name, but different parameter lists; thus you are not overriding, and are instead overloading.
Upvotes: 0
Reputation: 238311
How can I make it work?
You cannot make it work without changing the premises. void(Aa&)
cannot override void(A&)
. The parameter types must match.
Generally in object oriented programming, an overriding function cannot never have more strict parameter type.
Some object oriented languages support contravariant parameters in derived functions, which allows overriding with a function that accepts a more general parameter. For example, member function accepting `A&` could override a member function accepting `Aa&` (i.e. other way around compared to your attempt). However, C++ does not support contravariant parameters. The parameter types must match exactly.Perhaps dynamic polymorphism isn't what you need. Perhaps you need static polymorphism (templates):
template<
std::derived_from<A> TA
// or if you don't have concepts:
// class TA
>
struct B{
void foo(TA&) {
// use somehow
}
};
using Bb = B<Aa>;
Upvotes: 1
Reputation: 37647
lets assume it is possible/compiles and add extra class:
struct A{ void f()=0; };
struct Aa : A{ int x; void f(){} };
struct Ab : A{ double x; void f(){} };
struct B{
void foo(A&)=0;
};
struct Bb : B{
void foo(Aa&);
};
Now how this should work?
std::unique_ptr<B> p = std::make_unique<Bb>;
Ab a;
p->foo(a); // ???
how overridden function Bb::foo
should handle this scenario? It expected something of type Aa
, but got Ab
which is not child of Aa
. From B::foo
perspective this call is perfectly fine since Ab
is child of A
.
This should give you a hint why compiler didn't do what you have expected.
Upvotes: 1