Почему boost:: noncopyable требует наследования
Добавление любого не подлежащего копированию элемента в класс предотвратит автоматическое создание операции копирования и назначения. Почему boost требует наследования для использования noncopyable?
Я думаю, что я не одинок в своем стилистическом предпочтении
class MyUtility : public MyBase
{
noncopyable guard;
...
};
в отличие от
class MyUtility : public MyBase , private noncopyable
{
...
};
Дейв Абрахамс - умный парень, поэтому он, вероятно, рассмотрел эту возможность. Что мне не хватает? Что делает наследование?
Ответы
Ответ 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;
};