c ++ 由clang 重载虚函数警告?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18515183/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c++ overloaded virtual function warning by clang?
提问by Jean-Denis Muys
clang emits a warning when compiling the following code:
编译以下代码时,clang 会发出警告:
struct Base
{
virtual void * get(char* e);
// virtual void * get(char* e, int index);
};
struct Derived: public Base {
virtual void * get(char* e, int index);
};
The warning is:
警告是:
warning: 'Derived::get' hides overloaded virtual function [-Woverloaded-virtual]
(the said warning needs to be enabled of course).
(当然需要启用所述警告)。
I don't understand why. Note that uncommenting the same declaration in Base shuts the warning up. My understanding is that since the two get() functions have different signatures, there can be no hiding.
我不明白为什么。请注意,在 Base 中取消注释相同的声明会关闭警告。我的理解是,由于两个 get() 函数具有不同的签名,因此无法隐藏。
Is clang right? Why?
叮当正确吗?为什么?
Note this is on MacOS X, running a recent version of Xcode.
请注意,这是在 MacOS X 上运行的最新版本的 Xcode。
clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)
Update: same behavior with Xcode 4.6.3.
更新:与 Xcode 4.6.3 相同的行为。
回答by R. Martinho Fernandes
This warning is there to prevent accidental hiding of overloads when overriding is intended. Consider a slightly different example:
这个警告是为了防止在打算覆盖时意外隐藏重载。考虑一个稍微不同的例子:
struct chart; // let's pretend this exists
struct Base
{
virtual void* get(char* e);
};
struct Derived: public Base {
virtual void* get(chart* e); // typo, we wanted to override the same function
};
As it is a warning, it doesn't necessarily mean it is a mistake, but it might indicate one. Usually such warnings have a means of shutting them off by being more explicit and letting the compiler know you did intend what you wrote. I believe in this case you can do the following:
因为它是警告,所以并不一定意味着这是一个错误,但它可能表明一个错误。通常,此类警告可以通过更明确的方式将它们关闭,并让编译器知道您确实是有意编写的。我相信在这种情况下,您可以执行以下操作:
struct Derived: public Base {
using Base::get; // tell the compiler we want both the get from Base and ours
virtual void * get(char* e, int index);
};
回答by Pedro
Another way of disabling the warning keeping the struct public interface intact would be:
另一种禁用警告保持结构公共接口完整的方法是:
struct Derived: public Base
{
virtual void * get(char* e, int index);
private:
using Base::get;
};
This disallows a consumer of Derived
to call Derived::get(char* e)
while silencing the warning:
这不允许消费者在静音警告时Derived
调用Derived::get(char* e)
:
Derived der;
der.get("", 0); //Allowed
der.get(""); //Compilation error
回答by Ad N
R. Martinho Fernandessolution's is perfectly valid if you actually want to bring the get()
method taking a single char* argument into Derived
scope.
R. Martinho Fernandes 的解决方案是完全有效的,如果您真的想将get()
采用单个 char* 参数的方法引入Derived
范围。
Actually, in the snippet you provided, there is no need for virtual methods (since Base and Derived do not share any method with the same signature).
实际上,在您提供的代码段中,不需要虚拟方法(因为 Base 和 Derived 不共享任何具有相同签名的方法)。
Assuming there is actually a need for polymorphism, the hiding behavior could nonetheless be what is intended. In this case, it is possible to locally disable Clang's warning, with the following pragma :
假设实际上需要多态性,隐藏行为仍然可以是预期的。在这种情况下,可以使用以下编译指示在本地禁用 Clang 的警告:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
// Member declaration raising the warning.
#pragma clang diagnostic pop
回答by WormholeWizard
Warning means, that there will be no void * get(char* e) function in the scope of Derived class, cause it hidden by another method with same name. Compiler won't search for function in base classes if derived class has at least one method with specified name, even if it has another arguments.
警告意味着,派生类的范围内不会有 void * get(char* e) 函数,导致它被另一个同名的方法隐藏。如果派生类至少有一个具有指定名称的方法,即使它有另一个参数,编译器也不会在基类中搜索函数。
This sample code won't compile:
此示例代码无法编译:
class A
{
public:
virtual void Foo() {}
};
class B : public A
{
public:
virtual void Foo(int a) {}
};
int main()
{
B b;
b.Foo();
return 0;
}