Я читал 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=
.
Обратите внимание, что 'Data & sliced_data = usable_obj;' не разрезает. Для среза вам нужно «Data sliced_data = usable_obj;» – NathanOliver
@NathanOliver Он также не вызывает никакого оператора '' '' вообще. Для чего левая сторона? Это стандартная декларация с обязательной инициализацией. Но потом я думаю, что OP после этого ссылался на линию, и я менее уверен в том, что там происходит. Я думаю, это зависит от того, является ли 'operator =' виртуальным. –
@ PeterA.Schneider Поскольку 'returnSomeDataFromSomewhere()' возвращает 'Data', то присваивание просто изменит часть данных« Комбинированная », на которую ссылается ссылка. – NathanOliver