c++ перегруженная виртуальная функция предупреждение по clang?
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]
(указанное предупреждение должно быть включено, конечно).
Я не понимаю, почему. Обратите внимание, что раскомментирование одного и того же объявления в базе закрывает предупреждение. Я понимаю, что поскольку две функции 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 ответов:
это предупреждение предназначено для предотвращения случайного скрытия перегрузок при переопределении. Рассмотрим немного другой пример:
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); };
Р. Мартиньо Фернандес решение совершенно справедливо, если вы действительно хотите принести
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
другой способ отключить предупреждение, сохраняя структуру публичного интерфейса нетронутым будет:
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
предупреждение означает, что не будет 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; }
Comments