2016-11-30 7 views
1

Я читал this answer, в котором объяснялось, как нарезка будет изменять только одну часть объекта. Мне интересно, гарантировано или неопределено, что поведение нарезки объяснено в вероломном случае.Использование обрезки объектов для надежной копии из одного из нескольких базовых классов

Учитывая следующий класс структуры (которые я не могу изменить):

class Combined : public Data, public Handler 
{ 
    // no operator=() defined 
    // implements abstract and/or virtual methods from Handler 
    // methods access members from Data 
}; 

class Data 
{ 
    // no operator=() defined 
    // public members and public non-virtual methods only 
}; 

class Handler 
{ 
    // no operator=() defined 
    // contains abstract as well as virtual methods 
    // protected/private members 
}; 

можно надежно использования объекта нарезки для присвоения только Data части Combined, как таковые:

// Declaration 
Data returnSomeDataFromSomewhere(); 

// real work starts here 
Combined usable_obj; 

Data& sliced_data = usable_obj; 
sliced_data = returnSomeDataFromSomewhere(); 

usable_obj.actOnData(); 

или даже

Combined usable_obj; 
usable_obj.initialise(); 
usable_obj = returnSomeDataFromSomewhere(); 
usable_obj.actOnData(); 

Ответ от this question предполагает, что явно вызывающий Combined.Data::operator= (или он Combined::Data::operator=?) Достигает такого же эффекта. Он выглядит так же, как назначение объекту Data&, но меня смущает предостережение о нарушении инварианта производного класса.

Если нарезка является неопределенным поведением, я всегда могу создать временный объект Data и копировать каждый элемент отдельно, поскольку он является общедоступным, но я бы предпочел не делать этого, если в Data есть 200 членов.

Однако, если поведение нарезки гарантировано, есть ли какие-либо подводные камни, о которых я должен знать?


EDIT: Добавлены ограничения на классы, не имеющие operator=.

+1

Обратите внимание, что 'Data & sliced_data = usable_obj;' не разрезает. Для среза вам нужно «Data sliced_data = usable_obj;» – NathanOliver

+0

@NathanOliver Он также не вызывает никакого оператора '' '' вообще. Для чего левая сторона? Это стандартная декларация с обязательной инициализацией. Но потом я думаю, что OP после этого ссылался на линию, и я менее уверен в том, что там происходит. Я думаю, это зависит от того, является ли 'operator =' виртуальным. –

+0

@ PeterA.Schneider Поскольку 'returnSomeDataFromSomewhere()' возвращает 'Data', то присваивание просто изменит часть данных« Комбинированная », на которую ссылается ссылка. – NathanOliver

ответ

1

Я буду прыгать.

Прежде всего, это не разрезание, как поясняется в комментарии.

Это просто вызов функции, определенной в базовом классе. Это одна из функций, которые являются особыми, но не , что специальный (без магии). Реализация по умолчанию состоит в том, чтобы скопировать элементы объекта с правой стороны (который является аргументом operator=) соответствующим членам объекта, для которого вызывается функция-член, которая является левой стороной. Насколько я вижу, это должно быть безопасным для языка. (Конечно, может быть, что эта частичная смена вызывающего пользователя логически проблематична, поскольку она нарушает инварианты Combined.)

+0

Я очень просвещен. Имея другую перспективу, подкрепленную проницательностью, это удивительная вещь =) Я оставлю это открытым, возможно, на день или два, но похоже, что вы получаете тик. – aerobot

 Смежные вопросы

  • Нет связанных вопросов^_^