MISRA C++:2008 Rule 10-3-1

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

Описание

Управляйте определением

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

Объяснение

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

Реализация Polyspace

Средство проверки также повышает нарушение, если функция членства базового класса переопределена в производном классе без virtual ключевое слово.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

class Base {
    public:
      virtual void foo() {
     }
};

class Intermediate1: public virtual Base {
    public:
      virtual void foo() { //Noncompliant
      }    
};

class Intermediate2: public virtual Base {
    public:
       void bar() {
          foo();  // Calls Base::foo()
      }    
};

class Final: public Intermediate1, public Intermediate2 {
};

void main() {
    Intermediate2 intermediate2Obj;
    intermediate2Obj.bar(); // Calls Base::foo()
    Final finalObj;
    finalObj.bar(); //Calls Intermediate1::foo() 
                    //but you might expect Base::foo()
}

В этом примере, virtual функциональный foo задан в базовом классе Base и также в производном классе Intermediate1.

Потенциальный источник беспорядка может быть следующим. Класс Final выводит из Intermediate1 и также выводит из Base через другой путь с помощью Intermediate2.

  • Когда Intermediate2 вызовы объектов функциональный bar это вызывает функциональный foo, реализация foo в Base называется. Intermediate2 объект не знает о реализации в Intermediate1.

  • Однако, когда Final вызовы объектов тот же функциональный bar это вызывает функциональный foo, реализация foo в Intermediate1 называется из-за преобладания большего количества производного класса.

Вы можете видеть неожиданные результаты, если вы не принимаете это поведение во внимание.

Чтобы предотвратить эту проблему, объявите функцию как чистую виртуальный в базовом классе. Например, можно объявить класс Base можно следующим образом:

class Base {
    public:
      virtual void foo()=0;
};

void Base::foo() {
      //You can still define Base::foo()
}

Проверяйте информацию

Группа: производные классы
Категория: необходимый
Введенный в R2013b