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()函数具有不同的签名,因此不能隐藏。
clang对吗?为什么呢?
请注意,这是在MacOS X上运行最新版本的Xcode。
clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)
更新:与Xcode 4.6.3相同的行为。
答案 0 :(得分:105)
此警告用于防止在超控时意外隐藏过载。考虑一个稍微不同的例子:
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);
};
答案 1 :(得分:22)
<强> R上。 Martinho Fernandes 解决方案是完全有效的,如果你真的想让get()
方法将一个char *参数带入Derived
范围。
实际上,在您提供的代码段中,不需要虚拟方法(因为Base和Derived不共享任何具有相同签名的方法)。
假设实际上需要多态性,隐藏行为可能仍然是预期的。 在这种情况下,可以使用以下编译指示在本地禁用Clang的警告:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
// Member declaration raising the warning.
#pragma clang diagnostic pop
答案 2 :(得分:20)
禁用保持struct public interface完整性的警告的另一种方法是:
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
答案 3 :(得分:11)
警告意味着没有 void * get(char * e) 函数在Derived类的范围内,导致它被另一个具有相同名称的方法隐藏。 如果派生类至少有一个具有指定名称的方法,即使它有另一个参数,编译器也不会在基类中搜索函数。
此示例代码无法编译:
class A
{
public:
virtual void Foo() {}
};
class B : public A
{
public:
virtual void Foo(int a) {}
};
int main()
{
B b;
b.Foo();
return 0;
}