AUTOSAR C++14 Rule 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