【发布时间】:2018-07-16 07:04:30
【问题描述】:
我正在集成其他开发人员的代码库。我偶然发现了以下情况:
#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);
}
使用g++ -Wall 编译此代码不会出现警告,但使用clang++ -Wall 我得到:
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.
两种情况下的输出都是:
B::test(1, 2)
A::test(1)
如何解决这种情况?对我来说没有明确的路径,因为不清楚原始程序员的意图是什么。
- 可能是他想在
B实例中隐藏A::test的版本,并且只使用带有附加参数的版本(我认为这里就是这种情况)。 - 但我可以使用(注释掉的)
using A::test语句来消除警告,但调用b.test(1)将直接调用A::test,忽略过载。很可能原作者也不想在B类中公开A::test。 -
另一个想法是添加缺少的重载并使其引发异常,例如(在
B):void test(int a) { throw std::logic_error("unsupported function overload"); }但这感觉很糟糕,因为它是运行时的事情,我认为编译时应该已经出现错误或警告。
是否有一种规范的方法可以重载A::test 并以不需要使用-Wno-overloaded-virtual 的方式消除警告?
当前解决方案:
class B: public A
{
private:
using A::test;
public:
...
};
这消除了警告,如果调用b.test(1) 将给出错误。当然,它仍然可以调用A::test...
【问题讨论】:
-
由于没有重写函数,所以不需要创建为
virtual。 -
为什么不问问原作者的意图呢?
-
@liliscent 好吧,我不知道他的意图(100% 确定),但我有一个想法(
-
@Olaf Dietsche 他目前不可用:/ 否则我当然会有 :)
-
@UKMonkey 接口就是合约。通过公开从 A 派生,您承诺维护 A 的合同。破坏
A::test会破坏承诺,所以不要这样做
标签: c++ overloading clang++ derived-class