exponenta event banner

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. The 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