Предупреждение об отсутствии виртуального ключевого слова - PullRequest
7 голосов
/ 16 декабря 2009

Недавно у меня была неприятная проблема, которая сводилась к очень простой ошибке кодирования. Рассмотрим следующий код:

#include <iostream>

class Base
{
public:
    void func() { std::cout << "BASE" << std::endl; }
};

class Derived : public Base
{
public:
    virtual void func() { std::cout << "DERIVED" << std::endl; }
};

int main(int argc, char* argv[])
{
    Base* obj = new Derived;
    obj->func();
    delete obj;

    return 0;
}

Выход

БАЗА

Очевидно (для этого случая) я намеревался поместить виртуальное ключевое слово в Base :: func, чтобы Derived :: func вызывался в main. Я понимаю, что это (вероятно) разрешено стандартом c ++, и, возможно, по уважительной причине, но мне кажется, что в 99% случаев это будет ошибкой кодирования. Однако когда я скомпилировал с использованием g ++ и всех опций -Wblah, о которых я мог подумать, предупреждений не было.

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

Ответы [ 3 ]

5 голосов
/ 16 декабря 2009

В Visual C ++ вы можете использовать расширение override. Как это:

virtual void func() override { std::cout << "DERIVED" << std::endl; }

Это выдаст ошибку, если функция не переопределит метод базового класса. Я использую это для ВСЕХ виртуальных функций. Обычно я определяю макрос следующим образом:

#ifdef _MSC_VER
#define OVERRIDE override
#else
#define OVERRIDE
#endif

Так что я могу использовать это так:

virtual void func() OVERRIDE { std::cout << "DERIVED" << std::endl; }

Я искал что-то подобное в g ++, но не смог найти похожую концепцию.

Единственное, что мне не нравится в Visual C ++, это то, что компилятор не может требовать его (или хотя бы предупреждать) для всех переопределенных функций.

3 голосов
/ 16 декабря 2009

Я не знаю ни одного флага g ++, который бы выдавал предупреждение (не говоря о том, что его нет), но я бы сказал, что это довольно редкая ошибка. Большинство людей сначала пишут базовый класс как интерфейс, использующий чисто виртуальные функции. Если бы вы сказали:

void func() = 0;

тогда вы получите синтаксическую ошибку.

1 голос
/ 19 июня 2010

человек GCC

-Woverloaded-virtual (только для C ++ и Objective-C ++) Предупреждать, когда объявление функции скрывает виртуальные функции от базового класса. Например, в:

           struct A {
             virtual void f();
           };

           struct B: public A {
             void f(int);
           };

   the "A" class version of "f" is hidden in "B", and code like:

           B* b;
           b->f();

   will fail to compile.
...