gcc Woverloaded-виртуальные предупреждения - PullRequest
17 голосов
/ 03 апреля 2012

Следующий код C ++, который я считаю корректным, но выдает некоторые предупреждения при компиляции с "-Woverloaded-virtual", является ложным предупреждением или существует реальная проблема с этим кодом?

Если это фиктивное предупреждение, что я могу сделать, чтобы избежать его, определите все виртуальные варианты исключений в производных, чтобы получить предупреждение, но, возможно, это лучшее решение

Команда G ++:

   g++ -c -Woverloaded-virtual test.cpp 
test.cpp:22:18: warning: ‘virtual void intermediate::exception(const char*)’ was hidden [-Woverloaded-virtual]
test.cpp:32:18: warning:   by ‘virtual void derived::exception()’ [-Woverloaded-virtual]

C ++ код

using namespace std;

class base
{
public:

    virtual void exception() = 0;
    virtual void exception(const char*) = 0;
};

class intermediate : public base
{
public:

    virtual void exception()
    {
    cerr << "unknown exception" << endl;
    }

    virtual void exception(const char* msg)
    {
    cerr << "exception: " << msg << endl;
    }
};

class derived : public intermediate
{
public:

    virtual void exception() 
    { 
        intermediate::exception("derived:unknown exception");
    }
};

Ответы [ 3 ]

20 голосов
/ 03 апреля 2012

Предупреждение означает, что:
Если вы не используете динамическую диспетчеризацию, тогда ваш объект класса derived может вызывать только

 void exception()     

, и он будет скрывать все одноименные методы базового класса.intermediate.

Чтобы ваш производный объект класса мог вызывать все методы с одинаковыми именами в базовом классе intermediate, вам необходимо добавить следующую строку в ваш derived класс.

 using intermediate::exception;

Конечно, вы в лучшем положении, чтобы решить, если это проблема или нет.

14 голосов
/ 03 апреля 2012

Предупреждение связано с тем, что вы не можете вызвать derived::exception(const char*) для объекта типа derived (или через указатель на derived), даже если родительский класс определяет его, и он является виртуальным (так что вы ожидал, что он будет доступен в derived). Чтобы удалить предупреждение, вам нужно выставить эту функцию-член в derived:

class derived : public intermediate 
{ 
public: 
  virtual void exception(const char* msg) {intermediate::exception(msg);}
  virtual void exception()  
  {  
    intermediate::exception("derived:unknown exception"); 
  } 
}; 

Или, если вы не хотите показывать это другим, объявите это как частное без определения.

class derived : public intermediate 
{ 
public: 
  virtual void exception()  
  {  
    intermediate::exception("derived:unknown exception"); 
  } 
private:
  void exception(const char* tmp);
}; 

ОБНОВЛЕНИЕ: После двойной проверки (и как указал Als) директивы using вы можете сделать это тоже:

class derived : public intermediate 
{ 
public: 
  using intermediate::exception; // imports both declarations from intermediate
  virtual void exception() // will not clash with the imported declaration of the
                           // same signature, but properly overriders the parent
                           // class's defition
  {  
    intermediate::exception("derived:unknown exception"); 
  } 
}; 
0 голосов
/ 25 апреля 2013

Пожалуйста, переопределите функцию:

virtual void exception(const char* msg); в классе «производные».

Теперь ваш код будет компилироваться без каких-либо предупреждений.

...