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