Как сделать этот объект C++ не копируемым?


посмотреть название.

Я:

class Foo {
   private:
     Foo();
   public:
     static Foo* create();
}

что мне нужно сделать отсюда, чтобы сделать Foo не копируемым?

спасибо!

10   59   2010-02-01 01:59:15

10 ответов:

class Foo {
   private:
     Foo();
     Foo( const Foo& ); // 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

изменить: версия C++11 Если у вас есть компилятор, поддерживающий эту функцию:

class Foo {
   private:
     Foo();
     Foo( const Foo& ) = 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);
};

ссылка из таблицы стилей google

#include <boost/utility.hpp>
class Foo : boost::noncopyable {...

но как однажды сказал Скотт Мейерс..."Это прекрасный класс, просто я нахожу имя немного un, err non natural" или что-то в этом роде.

чтобы добавить немного там.

традиционным решением является, как уже было сказано,объявить и Copy Constructor и Assignment Operator как private и не до определение них.

  • потому что они private, это приведет к Ошибка времени компиляции от тех, кто пытается использовать их, которые не имеют доступа к частным частям класса...
  • который оставляет друзей (и сам класс) для которых ошибка будет происходить в виде undefined symbol, либо в link-time (если вы проверяете для тех, кто там) или, скорее всего, в времени (при попытке загрузить библиотеку).

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


кроме того, стоит отметить, что эти свойства являются транзитивными по пути наследования и композиции: компилятор будет генерировать только версии по умолчанию 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&);
};

это почему наследование от этого класса (или использование его в качестве атрибута) будет эффективно препятствовать тому, чтобы ваш собственный класс был копируемым или назначаемым, если вы не определяете эти операторы самостоятельно.

обычно наследование выбирается по композиции там по 2 причинам:

  • объект эффективно Uncopyable, даже если полиморфизм не может быть полезным
  • наследование приводит к EBO или Empty Base Optimization, в то время как атрибут будет адресуемым и, таким образом, будет занимать память (в каждом экземпляре класса) даже если она фактически не нужна, компилятор имеет возможность не добавлять эти накладные расходы для базового класса.

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

Надежда это пролило некоторый свет на механизм.

В C++11 вы можете явно отключить создание конструктора копирования и назначения по умолчанию, поместив = delete после объявления.

С Википедия:

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
{
};

хорошей практикой в C++11 является объявление конструктора копирования и назначения как публично удаленные. Не удален в частном порядке,публично удалено:https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete