Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.80/20: Рейтинг темы: голосов - 20, средняя оценка - 4.80
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
#1

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

13.12.2014, 13:15. Просмотров 3532. Ответов 52
Метки нет (Все метки)

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

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

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.12.2014, 13:15
Ответы с готовыми решениями:

Запретить повторное копирование текста из listbox1 в listbox2
Здравствуйте, есть два листбокса ,два эдита и три кнопки, две из которых служат...

Для поля объекта запретить запись, но оставить чтение
Традиционное оформление объектов заключается в том, что поля-значения...

Копирование объекта в вектор
Пишу граф. движок, но проблема скорее всего не с opengl. Возникла проблема с...

Копирование объекта в поток
"Переданный объект-функция копируется в память, принадлежащую только что...

Копирование из временного объекта
1) Собственно, как работает такой конструктор? Хотелось бы какой-нибудь пример....

52
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
14.12.2014, 16:28  [ТС] #41
Цитата Сообщение от DrOffset Посмотреть сообщение
По первоначальной теме есть что добавить?
Есть. Есть агрегирующий конеретный класс, не являющийся предком других классов и имеющий как минимум один собственный именованный экземпляр. Все экземпляры данного класса декларируются только с помощью конструктора по умолчанию. Требуется запретить копирование экземпляров только данного класса и сделать так, чтоб всякое присваивание одного экземпляра другому было перемещающим, данные признаки не должны распространяться на потомки, если таковые появятся в будущем. Потомки копироваться должны и для них присваивание по умолчанию должно означать копирование. Нет ни какой сущности, которая могла бы объединить данный класс с каким либо другим и такая сущность не может иметь смысл.
0
Гром
211 / 130 / 28
Регистрация: 20.03.2009
Сообщений: 1,110
Записей в блоге: 16
Завершенные тесты: 1
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
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
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
Гром
211 / 130 / 28
Регистрация: 20.03.2009
Сообщений: 1,110
Записей в блоге: 16
Завершенные тесты: 1
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
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
14.12.2014, 16:56  [ТС] #45
Цитата Сообщение от Гром Посмотреть сообщение
Нарушение LSP, нет?
Нарушение белорусского музыканта? Не смешно. Нарушение легчайшей суперсимметричной частицы? Подавно.
0
Гром
211 / 130 / 28
Регистрация: 20.03.2009
Сообщений: 1,110
Записей в блоге: 16
Завершенные тесты: 1
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
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
14.12.2014, 17:08  [ТС] #47
А ни как проще нельзя было написать? Зачем обязательно нужны импортные аббревиатуры? Я то вику читать умею, но в тему может забрести кто угодно. И да, мне нужен именно не наследуемый признак.

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

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

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

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

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

К сожалению, я не могу позволить себе потратить ближайшие несколько месяцев на объяснение вам того ООП, каким оно является для меня и многих других людей, не совпадающих с вами, поэтому вынужден отправить вас гуглить информацию о данной интерпретации ООП. Данная ссылка будет хорошим началом для ваших поисков.
0
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
14.12.2014, 17:31  [ТС] #50
Цитата Сообщение от Гром Посмотреть сообщение
Человек и пет, унаследованные от GameObject - это уже другие классы, никак не связанные с унаследованными от NonCopyable, родом из другого проекта. К сожалению, у них оказались одинаковые имена с теми, другими.
При чём здесь имена классов? Я вообще то имел ввиду поле std::string Name.
0
Гром
211 / 130 / 28
Регистрация: 20.03.2009
Сообщений: 1,110
Записей в блоге: 16
Завершенные тесты: 1
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
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
14.12.2014, 18:01  [ТС] #52
Цитата Сообщение от Гром Посмотреть сообщение
никаких имен. Кличка есть у класса
Код C++
1
class Pet: NonCopyable;
Имя и фамилия есть у
По-английски даже название - это имя. Кроме того, прозвище (чем оно не кличка) - это тоже вид имени.
0
maritux
Заблокирован
14.12.2014, 21:31 #53
Croessmah, гром, дураки-минусовальщики.
0
14.12.2014, 21:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.12.2014, 21:31

Копирование объекта из бинарного файла
Привет всем. Вот код мэйн: int _tmain(int argc, _TCHAR* argv) { Matrix...

Что лучше использовать для свойств объекта?
Мне нужно хранить свойства каких то объектов. То есть, строка и для этой строки...

Полное (побитовое) копирование объекта одной строчкой кода. не ссылки
Добрый день, подскажите пожалуйста, как быстро и безболезненно можно...


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

Или воспользуйтесь поиском по форуму:
53
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru