84

编译以下代码时,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() 函数具有不同的签名,因此无法隐藏。

叮当是对的吗?为什么?

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

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

更新:与 Xcode 4.6.3 相同的行为。

4

4 回答 4

128

此警告用于防止在打算覆盖时意外隐藏过载。考虑一个稍微不同的例子:

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

因为它是一个警告,它并不一定意味着它是一个错误,但它可能表明一个错误。通常,此类警告有一种方法可以通过更明确的方式关闭它们,并让编译器知道您确实打算写什么。我相信在这种情况下,您可以执行以下操作:

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);
};
于 2013-08-29T15:38:11.263 回答
33

禁用保持结构公共接口完整的警告的另一种方法是:

struct Derived: public Base
{
    virtual void * get(char* e, int index);
private:
    using Base::get;
};

这不允许消费者在消除警告Derived时调用:Derived::get(char* e)

Derived der;
der.get("", 0); //Allowed
der.get("");    //Compilation error
于 2015-05-12T13:45:39.213 回答
26

如果您确实想将get()采用单个 char* 参数的方法引入Derived范围,R. Martinho Fernandes解决方案是完全有效的。

实际上,在您提供的代码段中,不需要虚拟方法(因为 Base 和 Derived 不共享任何具有相同签名的方法)。

假设实际上需要多态性,隐藏行为可能仍然是预期的。在这种情况下,可以使用以下 pragma 在本地禁用 Clang 的警告:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
    // Member declaration raising the warning.
#pragma clang diagnostic pop
于 2013-11-22T13:57:18.233 回答
19

警告意味着,在派生类的范围内不会有 void * get(char* e) 函数,导致它被另一个同名的方法隐藏。如果派生类至少有一个具有指定名称的方法,即使它有另一个参数,编译器也不会在基类中搜索函数。

此示例代码无法编译:

class A
{
public:
    virtual void Foo() {}
};

class B : public A
{
public:
    virtual void Foo(int a) {}
};


int main()
{
    B b;
    b.Foo();
    return 0;
}
于 2013-08-29T15:47:37.020 回答