C + + 重载虚函数警告?

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);
};

警告是:

warning: 'Derived::get' hides overloaded virtual function [-Woverloaded-virtual]

(当然需要启用上述警告)。

我不明白为什么。注意,在 Base 中取消注释相同的声明会关闭警告。我的理解是,由于这两个 get ()函数具有不同的签名,因此不可能有隐藏。

叮当是正确的吗? 为什么?

注意,这是在 MacOSX 上运行的 Xcode 的最新版本。

clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)

更新: Xcode 4.6.3的相同行为。

69536 次浏览

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);
};

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.

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;
}

R. Martinho Fernandes solution's is perfectly valid if you actually want to bring the get() method taking a single char* argument into Derived scope.

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).

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 :

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
// Member declaration raising the warning.
#pragma clang diagnostic pop

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 der;
der.get("", 0); //Allowed
der.get("");    //Compilation error