семантика копирования / перемещения / преобразования, когда производный объект был связан со ссылкой на базовый класс?

Я хочу понять C ++ настолько, насколько смогу. Если есть базовый класс B и производный класс D, D d; создать экземпляр производного объекта.

  1. B & rb = d;, rb относится к производному объекту d, Это делает НЕ создать новый объект базового класса. Так какая часть памяти делает rb Ссылаться на?

  2. B newb = d;Позвонит, позвоню конструктор копирования базового класса. объект d сначала будет привязан к типу параметра const B&, а затем создается новый объект базового класса.

  3. B newbb(static_cast<B>(d));Что будет достигнуто в этом утверждении?

Три утверждения выше — мой собственный способ понять copy/move/conversion объектов. Но они действительно смущают меня. Я не могу найти эффективный и четкий способ интерпретации кодов, хотя я прочитал соответствующую часть Стандарт C ++ 11.

Я надеюсь, что ответы, чтобы объяснить три утверждения с помощью цитаты кода. Что произошло во время копирования / перемещения / преобразования объекта.


Помогите! Надеюсь, ответы от вас, ребята!

2

Решение

В общем, все это должны быть операции копирования, иногда сначала с преобразованиями. Я расскажу об операциях перемещения ниже.

Часть 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, будут происходить в зависимости от того, какой из двух конструкторов был вызван.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]