Как я делаю этот объект C++ non-copyable?

См. заголовок.

Я имею:

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

Чему нужно, я делаю отсюда до, делают Foo un-copyable?

Спасибо!

64
задан Guy Avraham 14 December 2017 в 09:43
поделиться

8 ответов

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

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

class Foo {
   private:
     Foo();
     Foo( const Foo& ) = delete; // non construction-copyable
     Foo& operator=( const Foo& ) = delete; // non copyable
   public:
     static Foo* create();
}
89
ответ дан 24 November 2019 в 15:39
поделиться

Сделать конструктор копирования и оператора назначения частным. Просто декларация достаточно, вам не нужно предоставлять реализацию.

25
ответ дан 24 November 2019 в 15:39
поделиться

Сделайте конструктор Copy Constructor.

Foo(const Foo& src);

Вам не нужно его реализовать, просто заявляйте его в файл заголовка.

3
ответ дан 24 November 2019 в 15:39
поделиться

Типичный способ сделать объект C++ некопируемым - явно объявить конструктор копирования и оператор копирования-назначения, но не реализовывать их. Это не позволит компилятору создать свой собственный. (Обычно это делается в сочетании с объявлением их private так, чтобы он генерировал ошибку компиляции вместо ошибки компоновщика)

Также существует класс boost::noncopyable , от которого можно наследовать, что делает то, о чем я говорил выше.

4
ответ дан 24 November 2019 в 15:39
поделиться
#include <boost/utility.hpp>
class Foo : boost::noncopyable {...

Но как когда-то сказал Скотт Мейерс ... «Это хороший класс, это просто то, что я нахожу имя немного ООН, ошибаться не естественным», или что-то подобное.

17
ответ дан 24 November 2019 в 15:39
поделиться

Это то, что я использую:

/* 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
{
};
2
ответ дан 24 November 2019 в 15:39
поделиться

Еще один способ запретить конструктор копирования. Для удобства можно использовать макрос 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

18
ответ дан 24 November 2019 в 15:39
поделиться

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

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

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

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


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

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

// What does boost::noncopyable looks like >
class Uncopyable {
public:
  Uncopyable() {}

private:
  Uncopyable(const Uncopyable&);
  Uncopyable& operator=(const Uncopyable&);
};

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

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

  • Объект фактически Некопируемый , даже если полиморфизм может оказаться не таким полезным
  • Наследование приводит к EBO или Оптимизация пустой базы , в то время как атрибут будет адресуемым и, таким образом, будет занимать память (в каждом экземпляре класса), даже если он на самом деле не нужен, компилятор имеет возможность не добавлять эти накладные расходы для базовый класс.

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

Надеюсь, это прольет свет на механизм.

17
ответ дан 24 November 2019 в 15:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: