Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.70/79: Рейтинг темы: голосов - 79, средняя оценка - 4.70
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
1

Как лучше запретить копирование объекта?

13.12.2014, 13:15. Показов 15129. Ответов 57
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть класс, надо запретить копирование его экземпляров. Можно как то сделать, чтоб в интерфейсе класса вообще не было конструктора копии и оператора копирующего присваивания?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.12.2014, 13:15
Ответы с готовыми решениями:

Как запретить копирование с флешки?
Доброе утро! Поскажите, пожалуйста, как запретить копирование с флешки? Хочу распечатать...

Как запретить копирование диска?
Люди добрые !!! Мучаюсь уже третий день не как не могу сделать так чтобу ДВД видео могли увидеть...

Как обойти "запретить копирование"
Вкладка Параметры доставки - основные - галочка на запрет копирования. У получателя соответственно...

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

57
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.12.2014, 16:28  [ТС] 41
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
По первоначальной теме есть что добавить?
Есть. Есть агрегирующий конеретный класс, не являющийся предком других классов и имеющий как минимум один собственный именованный экземпляр. Все экземпляры данного класса декларируются только с помощью конструктора по умолчанию. Требуется запретить копирование экземпляров только данного класса и сделать так, чтоб всякое присваивание одного экземпляра другому было перемещающим, данные признаки не должны распространяться на потомки, если таковые появятся в будущем. Потомки копироваться должны и для них присваивание по умолчанию должно означать копирование. Нет ни какой сущности, которая могла бы объединить данный класс с каким либо другим и такая сущность не может иметь смысл.
0
212 / 131 / 28
Регистрация: 20.03.2009
Сообщений: 1,123
Записей в блоге: 16
14.12.2014, 16:37 42
Как сделать три (аналогично - десять-двадцать-сто...) класса некопируемых сущностей с минимальными затратами и с минимальным риском в одном (-двух-пятнадцати...) из них где-то случайно накосячить:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Human : NonCopyable
{
public:
Human(std::string firstName, std::string lastName);
std::string firstName() const;
std::string lastName() const;
private:
std::string FirstName, LastName;
};
 
class Pet : NonCopyable
{
public:
Pet(std::string Name, const Human& owner);
std::string name();
const Human& owner() const;
private:
std::string Name;
const Human& Owner;
};
 
class House : NonCopyable
{
public:
House();
void addHabitant(const Human* habitant);
void addPet(const Pet* pet);
private:
std::deque<Human*> Habitants;
std::deque<Pet*> Pets;
};
Еще остались вопросы по поводу того, зачем нужен такой NonCopyable, и как его правильно использовать?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.12.2014, 16:49  [ТС] 43
Цитата Сообщение от Гром Посмотреть сообщение
Как сделать три (аналогично - десять-двадцать-сто...) класса некопируемых сущностей с минимальными затратами и с минимальным риском в одном (-двух-пятнадцати...) из них где-то случайно накосячить:
Как сделать два-сто-тысячу сущностей, содержащих поле типа std::string и с минимальным риском в одном из них где-нибудь накосячить? Не смешно. Тем более, что проще накосячить при наследовании, чем в написании одного признака.

Добавлено через 4 минуты
Цитата Сообщение от Гром Посмотреть сообщение
class Human : NonCopyable { public: Human(std::string firstName, std::string lastName); std::string firstName() const; std::string lastName() const; private: std::string FirstName, LastName; }; class Pet : NonCopyable { public: Pet(std::string Name, const Human& owner); std::string name(); const Human& owner() const; private: std::string Name; const Human& Owner; }; class House : NonCopyable { public: House(); void addHabitant(const Human* habitant); void addPet(const Pet* pet); private: std::deque<Human*> Habitants; std::deque<Pet*> Pets; };
Чёрта с два. Человека с петом нельзя объединять ни какой сущностью кроме биологического надтаксона. Учите UML. Там ясно сказано, что прежде чем создавать базовый класс для нескольких других классов, следует убедиться в том, что общие признаки этих классов есть следствие родства самих классов. А отсюда единственная допустимая сущность, объединяющая человека с собакой - млекопитающее. А если с рыбой, то позвоночное. А если ты червей разводишь, то уже животное (мы тоже в этом царстве).
Поэтому
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Human : HumNonCopyable
{
public:
Human(std::string firstName, std::string lastName);
std::string firstName() const;
std::string lastName() const;
private:
std::string FirstName, LastName;
};
 
class Pet : PNonCopyable
{
public:
Pet(std::string Name, const Human& owner);
std::string name();
const Human& owner() const;
private:
std::string Name;
const Human& Owner;
};
 
class House : HomNonCopyable
{
public:
House();
void addHabitant(const Human* habitant);
void addPet(const Pet* pet);
private:
std::deque<Human*> Habitants;
std::deque<Pet*> Pets;
};
и тот же самый мифический риск где то накосячить добавляется к реальному риску криво унаследовать.
0
212 / 131 / 28
Регистрация: 20.03.2009
Сообщений: 1,123
Записей в блоге: 16
14.12.2014, 16:53 44
Цитата Сообщение от taras atavin Посмотреть сообщение
данные признаки не должны распространяться на потомки, если таковые появятся в будущем. Потомки копироваться должны и для них присваивание по умолчанию должно означать копирование.
Нарушение LSP, нет?
Только делать какой-нибудь некопирующий миксин к классу, и использовать его вместо самого класса.
Или что-то такого рода (не уверен, что скомпилируется, это только набросок):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
template<class T> class MaybeUncopyable
{
public:
MaybeUncopyable(const MaybeUncopyable& other)
 {
 *this = DoCopy<T>(other);
 }
MaybeUncopyable& operator=(const MaybeUncopyable& other)
 {
 *this = DoCopy<T>(other);
 }
};
 
class Man : public MaybeUncopyable<Man>
{
//...
};
template <class Man> Man& DoCopy(const Man& other)
{
char[(1 == 2) ? 1 : 0] unnamed;
return other;
}
template <class T> T& DoCopy(const T& other)
{
return other;
}
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.12.2014, 16:56  [ТС] 45
Цитата Сообщение от Гром Посмотреть сообщение
Нарушение LSP, нет?
Нарушение белорусского музыканта? Не смешно. Нарушение легчайшей суперсимметричной частицы? Подавно.
0
212 / 131 / 28
Регистрация: 20.03.2009
Сообщений: 1,123
Записей в блоге: 16
14.12.2014, 16:59 46
Цитата Сообщение от taras atavin Посмотреть сообщение
Человека с петом нельзя объединять ни какой сущностью кроме биологического надтаксона.
C++
1
2
3
4
5
6
7
8
9
10
11
class GameObject
{
//...
};
 
class Human : GameObject {/**/};
class Pet : GameObject {/**/};
class Car : GameObject {/**/};
class Book : GameObject {/**/};
class Star : GameObject {/**/};
class НЁХ : GameObject {/**/};
Как же я всю жизнь программировал-то?!111 Ведь человек и книга - вещи, которые в принципе не могут быть унаследованы от одного класса!!!

Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
Нарушение белорусского музыканта? Не смешно. Нарушение легчайшей суперсимметричной частицы? Подавно.
Нарушение Liskov Substitution Principle для тех, кто новичок в ООП. Смешно.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.12.2014, 17:08  [ТС] 47
А ни как проще нельзя было написать? Зачем обязательно нужны импортные аббревиатуры? Я то вику читать умею, но в тему может забрести кто угодно. И да, мне нужен именно не наследуемый признак.

Добавлено через 52 секунды
Цитата Сообщение от Гром Посмотреть сообщение
Как же я всю жизнь программировал-то?
Стаж программирования не означает понимания идеологии ООП.

Добавлено через 5 минут
Что у Ваших "игровых объектов" закономерно общего? Имя у человека и у пета? А я может пишу игру, в которой петы безымянны? Общие признаки/операции должны вытекать из родства классов, а не наоборот. И не надо смешивать наследование со случайным совпадением признаков не родственных сущностей, или операций над ними. Ладно ещё класс "существо", это ещё можно понять. Но звезда каким боком к человеку? Это уже не ООП.
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,285
14.12.2014, 17:26 48
Цитата Сообщение от taras atavin Посмотреть сообщение
Требуется запретить копирование экземпляров только данного класса и сделать так, чтоб всякое присваивание одного экземпляра другому было перемещающим, данные признаки не должны распространяться на потомки, если таковые появятся в будущем.
Можно в потомках просто не вызывать конструктор копирования/оператор присваивания базового класса.
В изначальном сообщении, к тому же, не было подобных деталей (особенно насчет перемещения). Тут стоит отметить, что как-только мы определили в классе собственные оператор\конструктор перемещения, то присваивающие их версии автоматически помечаются как deleted. Вернуть их в строй после этого можно только явно определив, если мы этого не сделаем, то класс так и останется перемещаемым, но некопируемым. И в этом случае можно обходиться без идиомы noncopyable вообще. Естественно это применимо только к С++11, в С++03 все несколько сложнее и noncopyable пришлось бы оставить. А функции перемещения заменить на явные swap.

Вот небольшая иллюстрация на примере массива.

Добавлено через 4 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
Там ясно сказано, что прежде чем создавать базовый класс для нескольких других классов, следует убедиться в том, что общие признаки этих классов есть следствие родства самих классов.
Я же говорил, что в С++ наследование применяется для разных целей. В том числе в разрез с каноническим использованием. Читай Саттера и Мейерса. Справедливости ради стоит отметить, что приватное наследование не реализует отношение "является", о которым ты говорил, т.е. оно не предполагает родства, именно поэтому оно здесь используется. И служит только в качестве сервисного средства, чтобы заставить компилятор контролировать нужные нам свойства класса (для чего и нужны mix-ins). Так что никаких основополагающих концепций мы не нарушили этим кодом.
0
212 / 131 / 28
Регистрация: 20.03.2009
Сообщений: 1,123
Записей в блоге: 16
14.12.2014, 17:29 49
Цитата Сообщение от taras atavin Посмотреть сообщение
Что у Ваших "игровых объектов" закономерно общего? Имя у человека и у пета? А я может пишу игру, в которой петы безымянны? Общие признаки/операции должны вытекать из родства классов, а не наоборот. И не надо смешивать наследование со случайным совпадением признаков не родственных сущностей, или операций над ними. Ладно ещё класс "существо", это ещё можно понять. Но звезда каким боком к человеку? Это уже не ООП.
Человек и пет, унаследованные от GameObject - это уже другие классы, никак не связанные с унаследованными от NonCopyable, родом из другого проекта. К сожалению, у них оказались одинаковые имена с теми, другими.

Эта пятерка классов имеет общее то, что является частью абстрактной (не путать с абстрактными классами, абстрактным мышлением и абстрактным искусством!) простенькой игры. Игровые объекты могут находиться на карте, взаимодействовать друг с другом, отображаться на экране и т.п. Поскольку игра простенькая, то мы не выделяем отдельно PhysicalObject, GraphicalObject, ScryptableObject и другие, и валим весь функционал в GameObject.

К сожалению, я не могу позволить себе потратить ближайшие несколько месяцев на объяснение вам того ООП, каким оно является для меня и многих других людей, не совпадающих с вами, поэтому вынужден отправить вас гуглить информацию о данной интерпретации ООП. Данная ссылка будет хорошим началом для ваших поисков.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.12.2014, 17:31  [ТС] 50
Цитата Сообщение от Гром Посмотреть сообщение
Человек и пет, унаследованные от GameObject - это уже другие классы, никак не связанные с унаследованными от NonCopyable, родом из другого проекта. К сожалению, у них оказались одинаковые имена с теми, другими.
При чём здесь имена классов? Я вообще то имел ввиду поле std::string Name.
0
212 / 131 / 28
Регистрация: 20.03.2009
Сообщений: 1,123
Записей в блоге: 16
14.12.2014, 17:54 51
Цитата Сообщение от taras atavin Посмотреть сообщение
При чём здесь имена классов? Я вообще то имел ввиду поле std::string Name.
Ни в одном из этих пяти классов
C++
1
2
3
4
5
6
class Human : GameObject {/**/};
class Pet : GameObject {/**/};
class Car : GameObject {/**/};
class Book : GameObject {/**/};
class Star : GameObject {/**/};
class НЁХ : GameObject {/**/};
нет поля Name. Оно есть только в одном из девяти упомянутых мною классах (не считая тех, что в посте 44) - в другом классе Pet.
Цитата Сообщение от taras atavin Посмотреть сообщение
Что у Ваших "игровых объектов" закономерно общего? Имя у человека и у пета?
Нет у классов
C++
1
2
class Human : GameObject {/**/};
class Pet : GameObject {/**/};
никаких имен. Кличка есть у класса
C++
1
class Pet: NonCopyable;
Имя и фамилия есть у
C++
1
class Human: NonCopyable;
Между тем, два вышеупомянутых класса (и еще три других) унаследованы от GameObject.

Еще раз. Ниже представлены четыре РАЗНЫХ класса (у двух пар из них, так уж случилось, имена совпадают; но эти пары из разных проектов, и находятся в разных файлах исходного кода):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Human : HumNonCopyable
{
public:
Human(std::string firstName, std::string lastName);
std::string firstName() const;
std::string lastName() const;
private:
std::string FirstName, LastName;
};
 
class Pet : PNonCopyable
{
public:
Pet(std::string Name, const Human& owner);
std::string name();
const Human& owner() const;
private:
std::string Name;
const Human& Owner;
};
 
class Human : GameObject {/**/};
class Pet : GameObject {/**/};
Sapienti, как говорится, sat.
Dixi.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.12.2014, 18:01  [ТС] 52
Цитата Сообщение от Гром Посмотреть сообщение
никаких имен. Кличка есть у класса
Код C++
1
class Pet: NonCopyable;
Имя и фамилия есть у
По-английски даже название - это имя. Кроме того, прозвище (чем оно не кличка) - это тоже вид имени.
0
Заблокирован
14.12.2014, 21:31 53
Croessmah, гром, дураки-минусовальщики.
0
3 / 3 / 0
Регистрация: 14.07.2012
Сообщений: 86
22.07.2022, 20:57 54
Прошу прощения за некропост, начал изучать SFML и столкнулся с данной задачей.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class noncopyable
{
protected:
    noncopyable() {}
    ~noncopyable() {}
private: 
    noncopyable(noncopyable const & );
    noncopyable& operator=(noncopyable const &);
};
 
//.......
 
class SomeType 
    : noncopyable // класс SomeType нельзя копировать
{
};
никак не могу понять логику этих двуx строчек: (noncopyable(noncopyable const & ))и (noncopyable& operator=(noncopyable const &)), что делает первая и вторя по отдельности ?
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
22.07.2022, 21:15 55
Цитата Сообщение от dnscheb Посмотреть сообщение
что делает первая и вторя по отдельности ?
Просто объявляют конструктор копирования и оператор присваивания.
Объявляют их в private, поэтому никто к ним доступа не имеет и еще оставляют без реализации эти функции.
Соответственно, у наследника компилятор не будет генерировать конструктор копирования.

В С++11 вы можете сделать так:
C++
1
2
noncopyable(noncopyable const & ) = delete;
noncopyable& operator=(noncopyable const &) = delete;
Добавлено через 2 минуты
Idioms/Non-copyable Mixin
1
3 / 3 / 0
Регистрация: 14.07.2012
Сообщений: 86
22.07.2022, 21:17 56
Croessmah, первая строчка объявляет оператор копирования , а вторая оператор присваивания ? правильно?
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
22.07.2022, 21:17 57
dnscheb, да
1
3 / 3 / 0
Регистрация: 14.07.2012
Сообщений: 86
22.07.2022, 21:18 58
Цитата Сообщение от Croessmah Посмотреть сообщение
да
спасибо!
0
22.07.2022, 21:18
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.07.2022, 21:18
Помогаю со студенческими работами здесь

Как запретить копирование текста из RichtextBox в буфер обмена?
Задача такая: выводить текст на форму так, чтобы его можно было только читать. Пробовал...

Как запретить заход одного объекта на другой?
Как запретить заход одного объекта на другой силами VS2008??? using System; using...

Как запретить создание объекта в таком случае
Есть код class Component{ virtual void doSomething() = 0; }; class Object{ public: ...

Как запретить использование метода из объекта класса, содержащегося в классе?
class a { public: void set(int x, int y) { mX = x; mY = y; } int getX() { return...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
58
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru