MISRA C ++:2008 правил 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