Макросы для запрещения копии класса и присвоения. Google-vs-QT

Помимо того, что можно пропускать cookie, могло бы быть некоторое поле (поля) в форме, которую Вы не ОТПРАВЛЯЕТЕ на веб-сервер. Лучший способ состоял бы в том, чтобы получить фактический POST от веб-браузера. Можно использовать LiveHTTPHeaders или WireShark, чтобы отследить трафик и подражать тому же поведению в сценарии.

35
задан user2672165 28 July 2015 в 09:51
поделиться

10 ответов

Это не имеет значения. Тип возврата не является частью сигнатуры функции, так как он не участвует в разрешении перегрузки. Поэтому, когда вы пытаетесь выполнить присвоение, оба объявления будут совпадать, независимо от того, используете ли вы возвращаемый тип.

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

45
ответ дан 27 November 2019 в 06:47
поделиться

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

boost :: noncopyable - это пример реализации. Он используется следующим образом:

class A : noncopyable
{
    ...
};
15
ответ дан 27 November 2019 в 06:47
поделиться

См. Boost.Utility, в частности boost :: noncopyable . Это не макрос, а базовый класс с частной копией и назначением. Это предотвращает создание компилятором неявного копирования и присваивания в производных классах.

edit: Извините, это не был ответ на исходный вопрос. Кстати, boost :: noncopyable использует ссылку на константу в качестве типа возвращаемого значения для оператора присваивания. У меня создалось впечатление, что тип возвращаемого значения не имеет значения, поскольку его нельзя использовать. Тем не менее, закрытие оператора не предотвращает его использование внутри класса или друзей, и в этом случае необычный тип возвращаемого значения (например, void, ссылка на константу и т. Д.) Может привести к ошибкам компиляции и выявить дополнительные ошибки.

9
ответ дан 27 November 2019 в 06:47
поделиться

Практической разницы нет. Сигнатуры операторов присваивания различаются только по стилю. Обычно оператор присваивания возвращает ссылку, чтобы разрешить цепочку:

a = b = c;

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

5
ответ дан 27 November 2019 в 06:47
поделиться

Из стандарта, 12.8, пункт 9: «Объявленный пользователем оператор присваивания копии X :: operator = является нестатической нешаблонной функцией-членом класса X только с одним параметром типа X , X & , const X & , volatile X & или const volatile X & ". В нем ничего не говорится о типе возвращаемого значения, поэтому допустим любой тип возвращаемого значения.

В разделе 10 говорится: «Если в определении класса явно не объявляется оператор присваивания копии, он объявляется неявно».

Следовательно, объявление any ] X :: operator = (const X &) (или любой другой из указанных типов присваивания) достаточно. Ни тело, ни тип возвращаемого значения не имеют значения, если оператор никогда не будет использоваться.

Таким образом, это стилистическая разница: один макрос выполняет то, что мы, вероятно, ожидаем, а другой сохраняет несколько символов и выполняет работу способом, который может удивить некоторых. Я считаю, что макрос Qt стилистически лучше. Поскольку мы говорим о макросах, мы не говорим о том, что программист должен вводить что-то лишнее, и неумение удивить людей - это хорошо для языковой конструкции.

4
ответ дан 27 November 2019 в 06:47
поделиться

Другие уже ответили, почему разрешено иметь разные возвращаемые значения для operator =; IMHO jalf сказал это лучше всего .

Однако вы можете задаться вопросом , почему Google использует другой тип возврата, и я подозреваю, что это так:

Вам не нужно повторять имя типа при отключении такого оператора присваивания. Обычно имя типа является самой длинной частью объявления.

Конечно, эта причина недействительна, учитывая, что используется макрос, но все же - старые привычки трудно избавиться. : -)

2
ответ дан 27 November 2019 в 06:47
поделиться

Оба служат одной цели

Как только вы напишете это:

Class &operator=(const Class &);

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

1
ответ дан 27 November 2019 в 06:47
поделиться

Версия Qt обратно совместима, а версия Google - нет.

Если вы разработаете свою библиотеку и откажетесь от использования присваивания до того, как полностью удалите ее, в Qt, скорее всего, сохранится подпись он изначально имел. В этом случае старое приложение будет продолжать работать с новой версией библиотеки (однако они не будут компилировать с более новой версией).

Макрос Google не имеет такого свойства.

1
ответ дан 27 November 2019 в 06:47
поделиться

Между прочим, если у вас есть доступ к библиотекам Boost (у вас их нет? Почему, черт возьми, нет ??), в библиотеке утилит был некопируемый класс для долгое время:

class YourNonCopyableClass : boost::noncopyable {

Яснее ИМХО.

0
ответ дан 27 November 2019 в 06:47
поделиться

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

Лично я предпочитаю идиома того, что класс наследуется в частном порядке от пустого не копируемого базового класса (например, boost :: noncopyable, но у меня есть собственный, поэтому я могу использовать его в проектах, у которых нет возможности boost). Оптимизация пустого базового класса обеспечивает нулевые накладные расходы, простоту, удобочитаемость и не зависит от ужасных функций макроса препроцессора.

Она также имеет то преимущество, что копирование и присваивание невозможно даже использовать внутри кода реализации класса - это '

1
ответ дан 27 November 2019 в 06:47
поделиться
Другие вопросы по тегам:

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