Я хочу понять C ++ настолько, насколько смогу. Если есть базовый класс B
и производный класс D
, D d;
создать экземпляр производного объекта.
B & rb = d;
, rb
относится к производному объекту d
, Это делает НЕ создать новый объект базового класса. Так какая часть памяти делает rb
Ссылаться на?
B newb = d;
Позвонит, позвоню конструктор копирования базового класса. объект d
сначала будет привязан к типу параметра const B&
, а затем создается новый объект базового класса.
B newbb(static_cast<B>(d));
Что будет достигнуто в этом утверждении?
Три утверждения выше — мой собственный способ понять copy/move/conversion
объектов. Но они действительно смущают меня. Я не могу найти эффективный и четкий способ интерпретации кодов, хотя я прочитал соответствующую часть Стандарт C ++ 11.
Я надеюсь, что ответы, чтобы объяснить три утверждения с помощью цитаты кода. Что произошло во время копирования / перемещения / преобразования объекта.
Помогите! Надеюсь, ответы от вас, ребята!
В общем, все это должны быть операции копирования, иногда сначала с преобразованиями. Я расскажу об операциях перемещения ниже.
Часть 1:
Язык, который я собираюсь использовать, может немного отличаться от стандартного, но я склонен думать о rb
как относящийся ко всему объекту d
, Причина, по которой я говорю, что когда я делаю что-то подобное, D
почти всегда имеет хотя бы одну виртуальную функцию и любую виртуальную функцию, вызываемую через rb
будет запускать версию с D
не B
, Например, если у нас есть:
class B
{
public:
virtual int get_value() { return 10; }
};
class D: public B
{
public:
virtual int get_value() { return 20; }
};
затем rb.get_value()
вернет 20, а не 10, как вы, возможно, думаете.
Часть 2:
Это на самом деле то, что вы почти никогда не хотите делать. Что здесь происходит, так это d
превращается в B
с помощью процесса под названием «нарезка», который отбрасывает часть, которая была уникальной для D
и оставляет только B
часть, которая затем копируется для создания newb
, Это может показаться полезным, но на практике вы, вероятно, захотите создать полную копию d
а не частичный, или вы вообще не хотите создавать копию, а вместо этого хотите использовать указатель или ссылку на d
,
Если вы хотите создать полную копию, вы, вероятно, захотите, чтобы виртуальная функция делала копию, например так:
class B
{
public:
virtual B *clone()
{
return new B(*this);
}
};
class D: public B
{
public:
virtual B *clone()
{
return new D(*this);
}
};
Часть 3:
По сути это то же самое, что и часть 2 — наличие static_cast
просто делает разрезание явным, а не то, что компилятор делает автоматически. Опять же, это, вероятно, не то, что вы захотите делать очень часто.
В зависимости от контекста выражения, подобные тем, которые вы используете, могут вместо этого стать операциями перемещения. Например, если d
должны были быть уничтожены, компилятор мог бы распознать это и вызвать функцию перемещения вместо копии, поскольку перемещение, как правило, более эффективно. Например:
B foo()
{
D d;
return d;
}
В C ++ 11 оператор return может вызывать конструктор перемещения (если он существует), а не конструктор копирования для создания возвращаемого значения. Тем не менее, эффект должен быть довольно похожим — срезы, которые происходят в частях 2 и 3, будут происходить в зависимости от того, какой из двух конструкторов был вызван.
Других решений пока нет …