предотвратите случайное копирование объекта в C++

LSP иллюстрирования яркого примера (данный Дядей Входят в подкаст, который я недавно услышал) был то, как иногда что-то, что звучит правильным на естественном языке, не вполне работает в коде.

В математике, Square Rectangle. Действительно это - специализация прямоугольника. "", Заставляет Вас хотеть смоделировать это с наследованием. Однако, если в коде Вы сделали Square, происходят от Rectangle, тогда Square должно быть применимым где угодно, Вы ожидаете Rectangle. Это делает для некоторого странного поведения.

Предполагают, что Вы имели SetWidth и SetHeight методы на Вашем Rectangle базовый класс; это кажется совершенно логичным. Однако, если Ваш Rectangle ссылка указала Square, то SetWidth и SetHeight не имеет смысла, потому что установка той изменила бы другой для соответствия ему. В этом случае Square проваливает Тест Замены Liskov с [1 114], и абстракция наличия Square наследовались от [1 116], плохой.

enter image description here

Y'all должен проверить другое бесценное ТВЕРДЫЕ Принципы Мотивационные Плакаты .

17
задан Andy 27 August 2009 в 09:27
поделиться

5 ответов

Если в вашем стандарте кодирования указано, что «помните о способах предотвращения (случайного) копирования», я предполагаю, что они говорят не только о предотвращении копий из самих классов, но и о последствиях для производительности ненужных / случайные копии, когда используют классы.

Одна из основных причин неоправданной потери производительности в коде людей, плохо знакомых с C ++, - это ненужное копирование, обычно через временные библиотеки. Компиляторы становятся все лучше и лучше в решении, когда временные не нужны (см. «Хотите скорости? Передача по значению» , благодаря комментарию Конрада), но лучше всего научиться осознавать особенности внутренняя работа копирования и временных файлов в C ++ (среди прочего). Для меня чтение Эффективный C ++ действительно помогло мне начать.

11
ответ дан 30 November 2019 в 11:08
поделиться

Да, если сделать оператор присваивания и конструктор копирования закрытыми, вы не сможете создавать любую копию объекта с помощью стандартных методов (но если вам действительно нужна копия объекта, вы можете реализовать, например, Копировать (), который будет выполнять глубокое копирование).

Взгляните на boost :: noncopyable .

Обновление (относительно Тала Прессмана):

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

Я полагаю, что любое случайное копирование будет выполнено с использованием либо оператора присваивания, либо конструктор копирования. Так что сделать их частными на самом деле имеет смысл: если копирование объекта - дорогостоящая операция, то копирование должно быть явным: другой разработчик может непреднамеренно косвенно вызвать copy op, и компилятор проинформирует его,

21
ответ дан 30 November 2019 в 11:08
поделиться

Если вы используете ускорение, то самый простой способ предотвратить копирование класса - это унаследовать ваш класс от не копируемого :

#include <boost/noncopyable.hpp>

class Foo : private boost::noncopyable
{
}

Это проясняет ваше намерение, чем вручную сделать конструктор копирования и оператор присваивания закрытыми, и результат будет тот же.

10
ответ дан 30 November 2019 в 11:08
поделиться

Вы на правильном пути. Если вы не хотите использовать boost, вы можете сделать следующее: Сделать конструктор копирования и оператор присваивания копии частными и не реализовывать их. Таким образом, вы получите ошибку компилятора, если попытаетесь скопировать экземпляр.

2
ответ дан 30 November 2019 в 11:08
поделиться

Ваш список выглядит великолепно с точки зрения предотвращения ошибок, например, удаления одной и той же области памяти более одного раза из-за общих указателей из неявного копирования объектов.

Надеюсь, это так. также актуально; из утверждения «знайте, как можно предотвратить (случайное) копирование» вы можете принять это как означающее «осознавать непреднамеренное ненужное копирование». Это будет означать обстоятельства, которые могут повлиять на производительность. В очень простом примере ваши соглашения о кодировании могут означать, что вам следует предпочесть:

std::string text1( "some text" );

вместо:

std::string text1 = "some text";

Во втором случае будет создана временная строка для хранения «некоторого текста» перед вызовом оператора присваивания (форма копирования ), чтобы заполнить text1 «некоторым текстом».

0
ответ дан 30 November 2019 в 11:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: