Анализатор обнаружил потенциальную ошибку, связанную с тем, что объект производного класса был скопирован в объект базового класса, т.е. произошла срезка типа.
Если базовый и производный классы являются полиморфными (т.е. содержат виртуальные функции), то при таком копировании информация о переопределенных виртуальных функциях в производных классах будет утеряна. Это может привести к нарушению полиморфного поведения.
Другим фактом является то, что объект базового класса теряет информацию о полях производного класса, если конструктор копирования сгенерирован компилятором неявно (возможно даже и в случае определенного пользователем).
Рассмотрим следующий пример:
struct Base { int m_i; Base(int i) : m_i { i } { } virtual int getN() { return m_i; } }; struct Derived : public Base { int m_j; Derived(int i, int j) : Base { m_i }, m_j { j } { } virtual int getN() { return m_j; } }; void foo(Base obj) { std::cout << obj.getN() << "\n"; } void bar() { Derived d { 1, 2 }; foo(d); }
При передаче переменной 'd' в функцию 'foo' произойдет копирование, а функция 'getN' будет вызвана из класса 'Base'.
Чтобы избежать проблем, связанных со срезкой типа, стоит использовать указатели/ссылки:
void foo(Base &obj) { std::cout << obj.getN() << "\n"; }
В этом случае копирования не произойдет, и 'getN' будет вызвана из класса 'Derived'.
Если срезка типа все же необходима, то желательно определить явную операцию, которая это делает. Это спасет читателей кода от путаницы:
struct Base { .... }; struct Derived : public Base { .... Base copy_base(); .... }; void foo(Base obj); void bar() { Derived d { .... }; foo(d.copy_base()); }
Анализатор не выдает срабатывание в случае, если иерархия классов не содержит виртуальных функций и все нестатические поля располагаются в базовом классе:
struct Base { int m_i; int m_j; Base(int i, int j) : m_i { i }, m_j { j } { } int getI() { return m_i; } int getJ() { return m_j; } }; struct Derived : public Base { Derived(int i, int j) : Base(i, j) { } virtual int getN() { return m_j; } };
Данная диагностика классифицируется как:
|