Reputation: 12930
I am in the process of integrating a code base from another developer. I have stumbled over the following situation:
#include <iostream>
struct A
{
virtual void test(int a)
{
std::cout << "A::test(" << a << ')' << std::endl;
}
};
struct B : public A
{
// using A::test;
void test(int a, int b)
{
std::cout << "B::test(" << a << ", " << b << ')' << std::endl;
A::test(a);
}
};
int main()
{
B b;
b.test(1, 2);
}
Compiling this code gives no warnings with g++ -Wall
, but with clang++ -Wall
I get:
x.cpp:15:11: warning: 'B::test' hides overloaded virtual function [-Woverloaded-virtual]
void test(int a, int b)
^
x.cpp:5:19: note: hidden overloaded virtual function 'A::test' declared here: different number of parameters (1 vs 2)
virtual void test(int a)
^
1 warning generated.
Output in both cases would be:
B::test(1, 2)
A::test(1)
How to resolve this situation? For me there is no clear path, since it is unclear what is the intention of the original programmer.
A::test
in B
instances and only use the version with the additional argument (I think that's the case here).using A::test
statement which gets rid of the warning, but calling b.test(1)
would directly call into A::test
, ignoring the overload. Most probably the original author does not want to expose A::test
in B
classes, too.Another idea would be to add the missing overload and make it raise an exception, like (in B
):
void test(int a)
{
throw std::logic_error("unsupported function overload");
}
But this feels bad since it's a runtime thing and I think there should be an error or a warning on compilation already.
Is there a canonical way to overload A::test
and get rid of the warning in a way where I need not use -Wno-overloaded-virtual
?
Current solution:
class B: public A
{
private:
using A::test;
public:
...
};
This gets rid of the warning and will give an error if calling b.test(1)
. It still makes it possible to call A::test
on it of course ...
Upvotes: 0
Views: 580
Reputation: 6983
While you could make test(int) private in B, which will remove the warnings; you will end up with the situation that someone could trivially pass it as an "A" object and then call test(int) on it anyway. I would not worry about the intentions of the original engineer since there's a work around to call test(int) and make sure that what it does makes sense; even if that means throwing or failing to compile if used.
Upvotes: 1
Reputation: 409176
A possible solution or workaround might be to pull A::test
into the scope of B
, like
struct B : A
{
using A::test;
...
};
Then you can use plain test(a)
and A::test
should be called.
Upvotes: 2