Подтвердить что ты не робот

Почему boost:: noncopyable требует наследования

Добавление любого не подлежащего копированию элемента в класс предотвратит автоматическое создание операции копирования и назначения. Почему boost требует наследования для использования noncopyable?

Я думаю, что я не одинок в своем стилистическом предпочтении

class MyUtility : public MyBase
{
   noncopyable guard;
   ...
};

в отличие от

class MyUtility : public MyBase , private noncopyable
{
   ...
};

Дейв Абрахамс - умный парень, поэтому он, вероятно, рассмотрел эту возможность. Что мне не хватает? Что делает наследование?

4b9b3361

Ответ 1

Потому что sizeof(boost::noncopyable)!=0. Поэтому в этом случае размер вашего класса будет больше.

Здесь вы можете прочитать о пустой оптимизации базы. (смотрите раздел "4.7: Оптимизация пустых элементов" ).

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

Ответ 2

Если вы могли бы использовать noncopyable в качестве члена, для этого потребовался бы стандартный конструктор и деструктор по умолчанию. Тогда люди могут создавать экземпляры noncopyable или даже использовать его в качестве полиморфного базового класса без виртуального деструктора. Реализация без каких-либо публичных пользователей просто гарантирует, что она используется исключительно как класс политики.

Ответ 3

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

Ответ 4

Наиболее очевидная причина заключается в том, что производный класс "isA" не доступен, поэтому использование наследования имеет наибольший смысл. Тот факт, что использование его таким образом не увеличивает размер класса, также является сегодня соображением (но я думаю, что noncopiable предшествовало оптимизации пустого базового класса).

Ответ 5

Если вы опускаете обозначение private, оно становится почти как английский:

// English: this is my car, it is not copyable
class MyCar: noncopyable {};

// my truck is noncopyable, did i mention it also a vehicle?
class MyTruck: noncopyable, public MyVehicle {};

// My airplane is a vehicle, BTW it not copyable
class MyAirplane: public MyVehicle, noncopyable {};

Ответ 6

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

class VertexBuffer
{
   std::sr1::noncopyable<GLint> m_vbo;
   ...
};

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

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

class VertexBuffer
{
   std::sr1::noncopyable<GLint> m_vbo;
   std::sr1::zeroinitialized<int> m_vertexCount;
};