exponenta event banner

Правило AUTOSAR C++ 14 A12-8-6

Конструкторы копирования и перемещения и операторы назначения копирования и перемещения должны быть объявлены защищенными или определены как «= delete» в базовом классе

Описание

Определение правила

Конструкторы копирования и перемещения и операторы назначения копирования и перемещения должны быть объявлены защищенными или определены как «= delete» в базовом классе.

Объяснение

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

  • Объявление конструкторов копирования и перемещения и операторов назначения копирования и перемещения как protected.

  • Определение конструкторов копирования и перемещения и операторов назначения копирования и перемещения как "=delete".

Внедрение Polyspace

Polyspace ® помечает эти специальные функции-члены базового класса, если они не объявленыprotected или определено как =delete:

  • Конструктор копирования

  • Конструктор перемещения

  • Копировать оператор назначения

  • Оператор назначения перемещения

Polyspace указывает, какая специальная функция-член нарушает это правило.

Поиск неисправностей

Если вы ожидаете нарушения правила, но не видите его, обратитесь к разделу Нарушения стандартов кодирования не отображаются.

Примеры

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

#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
class A 
{                                           
  public:                                   
    int base_var;
    A() = default;                          
    A(A const&) = default;                //Noncompliant
    A(A&&) = default;                     //Noncompliant
    virtual ~A() = 0;                       
    A& operator=(A const&) = default;     //Noncompliant
    A& operator=(A&&) = default;          //Noncompliant
};                                          
class B : public A                          
{                                           
    int derived_var;
};                                          
class C //               
{                                           
  public:                                   
    int base_var;
    C() = default;                          
    virtual ~C() = 0;                       
                                            
  protected:                                
    C(C const&) = default;                //Compliant
    C(C&&) = default;                     //Compliant
    C& operator=(C const&) = default;     //Compliant
    C& operator=(C&&) = default;          //Compliant
};                                          
class D : public C                          
{
    int derived_var;
};
class E            
{                                            
  public:                                    
    int base_var;
    E() = default;                           
    virtual ~E() = default;                  
    E(E const&) = delete;                   //Compliant
    E(E&&) = delete;                        //Compliant
    E& operator=(E const&) = delete;        //Compliant
    E& operator=(E&&) = delete;             //Compliant
};

class F : public E                          
{
    int derived_var;
};
void Fn1() noexcept
{
  B obj1;
  B obj2;
  A* ptr1 = &obj1;
  A* ptr2 = &obj2;
  *ptr1 = *ptr2;             // Partial assignment only
  *ptr1 = std::move(*ptr2); // Partial move only
  D obj3;
  D obj4;
  C* ptr3 = &obj3;
  C* ptr4 = &obj4;
  // *ptr3 = *ptr4; // Compilation error 
  // *ptr3 = std::move(*ptr4); // Compilation error 
  F obj5;
  F obj6;
  E* ptr5 = &obj5;
  E* ptr6 = &obj6;
  // *ptr5 = *ptr6; // Compilation error 
  // *ptr5 = std::move(*ptr6); // Compilation error 
}

Класс A является базовым классом с конструкторами копирования и перемещения по умолчанию и операторами назначения копирования и перемещения по умолчанию. Класс B является производным от A и имеет переменную derived_var который отсутствует в A. В Fn1(), два указателя ptr1 и ptr2 создаются. Они являются объектами базового класса A, но указать на obj1 и obj2 соответственно, которые являются объектами производного класса B. Назначение A *ptr = &obj1; является примером полиморфного поведения, где можно объявить указатель базового класса и назначить ему объекты любого производного класса.

Поскольку ptr1 и ptr2 являются объектами базового класса A, операция копирования в *ptr1 = *ptr2 вызывает default копировать оператор назначения класса A. default семантика копирует только базовую часть obj2 в obj1. То есть obj2.derived_var не копируется в obj1.derived_var. Аналогичным образом, право собственности на obj2.derived_var не перемещен в obj1 по операции перемещения в *ptr1 = std::move(*ptr2). Чтобы избежать случайного срезания, подавьте операции копирования и перемещения в базовом классе иерархии классов. Polyspace помечает функции копирования и перемещения в базовом классе A поскольку эти функции не объявлены как protected не определено как =delete.

В классе C, функции копирования и перемещения подавляются объявлением конструкторов копирования и перемещения и операторов назначения копирования и перемещения protected. В классе E, операции копирования и перемещения подавляются объявлением этих специальных функций-членов как =delete. При вызове операций копирования или перемещения этих базовых классов компилятор создал ошибку. Определения базовых классов C и E соответствуют этому правилу.

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

Группа: Специальные функции-члены
Категория: Обязательно, Автоматизировано
Представлен в R2020a