почему boost :: noncopyable требует наследования - PullRequest
26 голосов
/ 28 января 2011

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

Мне кажется, я не одинок в своем стилистическом предпочтении

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

в отличие от

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

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

Ответы [ 6 ]

33 голосов
/ 28 января 2011

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

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

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

23 голосов
/ 28 января 2011

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

4 голосов
/ 28 января 2011

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

4 голосов
/ 28 января 2011

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

0 голосов
/ 27 мая 2019

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

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

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

Например, в предыдущем примере;Я могу скопировать собаку, так почему ваш автомобиль настолько особенный, что я не могу его скопировать?

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

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

Я немного опоздал на эту вечеринку, но есть ли у кого-нибудь еще предложения?

0 голосов
/ 01 февраля 2011

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

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

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

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