#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
}The Class A is a base class with default copy and move constructors
and default copy and move assignment operators. The class B is derived
from A and has a variable derived_var that is absent
in A. In Fn1(), two pointers ptr1
and ptr2 are created. They are objects of the base class
A, but point to obj1 and obj2
respectively, which are objects of the derived class B. The assignment
A *ptr = &obj1; is an example of polymorphic behavior where you can
declare a pointer of the base class and assign objects of any derived class to it.
Because ptr1 and ptr2 are objects of the base
class A, the copy operation in *ptr1 = *ptr2 invokes the
default copy assignment operator of class A. The
default semantics copies only the base part of obj2
into obj1. That is, obj2.derived_var is not copied
into obj1.derived_var. Similarly, the ownership of
obj2.derived_var is not moved to obj1 by the move
operation in *ptr1 = std::move(*ptr2). To avoid inadvertent slicing,
suppress the copy and move operations in the base class of a class hierarchy. Polyspace flags the copy and move functions in base class A because
these functions are neither declared as protected nor defined as
=delete.
In class C, the copy and move functions are suppressed by declaring
the copy and move constructors and copy assignment and move assignment operators
protected. In class E, the copy and move operations
are suppressed by declaring these special member functions as =delete. If
you invoke the copy or move operations of these base classes, the compiler generated an
error. The definitions of the base classes C and E are
compliant with this rule.