В моем коде есть случай, когда я хотел бы использовать нарезку объектов, но я пытаюсь определить, безопасно ли это делать. Пытаясь определить это, я запустил следующий пример:
#include <iostream>
using namespace std;class Dog{
public:
Dog( int x )
:x{x}
{
};
int x;
};class Spaniel: public Dog{
public:
Spaniel( int x, int y )
:Dog{x}, y{y}
{
}
int y;
};class Green{
public:
Green( int q )
:q{q}
{
}
int q;
};class GreenSpaniel: public Spaniel, public Green{
public:
GreenSpaniel( int x, int y, int q, int z )
:Spaniel{x,y}, Green{q}, z{z}
{
}
int z;
};int main(){
GreenSpaniel jerry{ 1,2,3,4 };
Green fred = jerry;
cout << fred.q << endl; //correctly displays "3"
return 0;
}
Я ожидал, что он вернет 1, потому что базовый класс не был самым верхним (root), но он отображает 3. Итак, мой вопрос: почему / как он показывает правильный ответ и это безопасная практика? Как изменится ваш ответ, если у любого из классов будут виртуальные таблицы? Если вы не считаете это безопасным, есть ли у вас какие-либо обходные пути для копирования базового объекта без полномочий root из производного объекта?
Я запустил это в Linux под GCC 4.6.3 с помощью следующей команды:
g++ -std=c++0x main.cc
Происходит то, что fred создается с использованием конструктора копирования, синтезированного компилятором, который принимает const Green&
в качестве аргумента. Он выполняет мелкую копию содержимого зеленой части Джерри.
вы бы видели тот же результат, если бы использовали
const Green& fred = jerry;
где копия не выполняется, вы просто получаете доступ к части Джерри Джерри, давая ему имя fred
,
Что касается другой части вопроса, в вашем дизайне нет ничего небезопасного, просто он «сложный», и вам нужно быть в курсе происходящего. Вы можете прочитать этот и связанные страницы для некоторого обсуждения по теме.
Конечно, вы можете определить свой собственный конструктор (ы) копирования / оператор (ы), имеющие другое поведение. Или вы можете просто запретить компилятору генерировать их
Традиционный способ справиться с этим — объявить конструктор частной копии и присвоение копии, а затем задокументировать, почему это так.
сделанный. В C ++ 2011 была представлена новая альтернатива, объявляющая копию
конструктор и оператор присваивания копии, но помечая как
удален. Происхождение из некопируемого проще и понятнее, и
не требует дополнительной документации.
Других решений пока нет …