См. главу.
У меня есть:
class Foo {
private:
Foo();
public:
static Foo* create();
}
Что мне нужно сделать, чтобы сделать Foo не скопированным?
Спасибо!
См. главу.
У меня есть:
class Foo {
private:
Foo();
public:
static Foo* create();
}
Что мне нужно сделать, чтобы сделать Foo не скопированным?
Спасибо!
class Foo {
private:
Foo();
Foo( const Foo& other ); // non construction-copyable
Foo& operator=( const Foo& ); // non copyable
public:
static Foo* create();
}
Если вы используете boost, вы также можете наследовать от noncopyable: http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp
EDIT: версия С++ 11, если у вас есть компилятор, поддерживающий эту функцию:
class Foo {
private:
Foo();
Foo( const Foo& other ) = delete; // non construction-copyable
Foo& operator=( const Foo& ) = delete; // non copyable
public:
static Foo* create();
}
Сделайте конструктор копирования и оператор присваивания приватным. Просто объявления достаточно, вам не нужно предоставлять реализацию.
Еще один способ запретить конструктор копирования. Для удобства можно использовать макрос DISALLOW_COPY_AND_ASSIGN:
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
Тогда в классе Foo:
class Foo {
public:
Foo(int f);
~Foo();
private:
DISALLOW_COPY_AND_ASSIGN(Foo);
};
#include <boost/utility.hpp>
class Foo : boost::noncopyable {...
Но как однажды сказал Скотт Майерс: "Это классный класс, просто я нахожу имя немного un, err non natural" или что-то в этом роде.
Чтобы добавить немного туда.
Традиционное решение, как уже было сказано, объявляет как Copy Constructor
, так и Assignment Operator
как private
, а не - define.
private
, это приведет к ошибке времени компиляции от любого, кто пытается использовать их, у которых нет доступа к частным частям класса...undefined symbol
, либо во время ссылки (если вы проверяете их там), либо, скорее всего, во время выполнения (при попытке загрузите библиотеку).Конечно, во втором случае это довольно беспокоит, потому что вам нужно сначала проверить свой код, так как у вас нет указателя на файл и строку, в которой происходит ошибка. К счастью, он ограничивается вашими методами и друзьями.
Кроме того, стоит отметить, что эти свойства транзитивны по пути наследования и композиции: компилятор будет генерировать только версии Default Constructor
, Copy Constructor
, Assignment Operator
и Destructor
по умолчанию, если это может.
Это означает, что для любого из четырех они автоматически генерируются только, если они доступны для всех баз и атрибутов класса.
// What does boost::noncopyable looks like >
class Uncopyable {
public:
Uncopyable() {}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
Вот почему наследование этого класса (или использование его как атрибута) эффективно предотвратит копирование или назначение вашего собственного класса, если вы сами не определите эти операторы.
Обычно наследование выбирается по составу по двум причинам:
Uncopyable
, даже если полиморфизм может быть не таким полезнымEBO
или Empty Base Optimization
, тогда как атрибут будет адресуемым и, таким образом, будет занимать память (в каждом экземпляре класса), даже если он на самом деле не нужен, компилятор имеет возможность не добавлять это служебные данные для базового класса.Вы также можете объявить операторы частными и не определять их в своем собственном классе, но код будет менее самодокументированным, и вы не сможете автоматически искать те классы, у которых есть это свойство (если у вас полноразмерный парсер).
Надеюсь, что это пролило некоторый свет на механизм.
В С++ 11 вы можете явно отключить создание конструктора копирования и назначения по умолчанию, разместив = delete
после объявления.
От Wikipedia:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable & operator=(const NonCopyable&) = delete;
};
То же самое относится и к классам.
Типичный способ сделать объект С++ не копируемый - явно объявить конструктор копирования и оператор присваивания копии, но не реализовать их. Это предотвратит создание компилятором собственного. (Обычно это делается в сочетании с объявлением их private
, чтобы он генерировал ошибку компиляции вместо ошибки компоновщика.)
Также существует класс boost::noncopyable
, который вы можете наследовать, что делает то, что я описал выше.
Сделать конструктор копирования закрытым.
Foo(const Foo& src);
Вам не нужно его реализовывать, просто объявите его в файле заголовка.
Это то, что я использую:
/* Utility classes */
struct NoCopy
{
public:
NoCopy() {}
private:
NoCopy(const NoCopy &);
};
struct NoAssign
{
private:
NoAssign &operator=(const NoAssign &);
};
struct NonInstantiable
{
private:
NonInstantiable();
};
struct NoCopyAssign : NoCopy, NoAssign
{
};
typedef NoCopyAssign NoAssignCopy;
В вашем случае:
struct Example : NoCopy
{
};