С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 23.10.2019
Сообщений: 12

Перегрузка оператора присваивания

23.12.2020, 15:34. Показов 1958. Ответов 17
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Всех приветствую, по заданию необходимо разработать шаблон структуры данных, сама структура представляет собой циклический двусвязный список, вот только всё, что я могу сделать со списком, это добавить элемент, а при попытке использовать другие методы (например, поиск элемента) выходит ошибка про отсутствие оператора присваивания.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
template<class T> class List
{
    class Node
    {
    public:
        T data;
        Node* next;
        Node* prev;
        Node(T n = 0) { data = n; next = nullptr; prev = nullptr; }
    };
 
    Node* pbeg, * pend;
public:
    List() { pbeg = nullptr; pend = nullptr; }
    ~List();
    void add(T data);
    Node* find(T i);
    Node* insert(T key, T data);
    bool remove(T key);
    void print();
};
 
template<class T>List<T>::~List()
{
    if (pbeg != nullptr)
    {
        Node* pv = pbeg;
        while (pv)
        {
            pv = pv->next; delete pbeg;
            pbeg = pv;
        }
    }
}
 
template<class T>void List<T>::print()
{
    Node* pv = pbeg;
    std::cout << std::endl << "list: ";
    while (pv)
    {
        std::cout << pv->data << ' ';
        pv = pv->next;
    }
    std::cout << std::endl;
}
 
template<class T> void List<T>::add(T data)
{
    Node* pv = new Node(data);
    if (pbeg == nullptr)
        pbeg = pend = pv;
    else
    {
        pv->prev = pend;
        pend->next = pv;
        pend = pv;
    }
}
 
template <typename T> typename List<T>::Node* List<T>::find(T i)
{
    Node* pv = pbeg;
    while (pv)
    {
        if (pv->data = data) break;
        pv = pv->next;
    }
    return pv;
}
 
template<typename T> typename List<T>::Node* List<T>::insert(T key, T data)
{
    if (Node* pkey = find(key))
    {
        Node* pv = new Node(data);
        pv->next = pkey->next;
        pv->prev = pkey;
        pkey->next = pv;
        if (pkey != pend)
            pv->next->prev = pv;
        else pend = pv;
        return pv;
    }
    return 0;
}
 
template<class T> bool List<T>::remove(T key)
{
    if (Node* pkey = find(key))
    {
        if (pkey == pbeg)
        {
            pbeg = pbeg->next;
            pbeg->prev = nullptr;
        }
        else if (pkey == pend)
        {
            pend = pend->prev;
            pend->next = nullptr;
        }
        else
        {
            pkey->prev->next = pkey->next;
            pkey->next->prev = pkey->prev;
        }
        delete pkey;
        return true;
    }
    return false;
}
Вот весь код, связанный со списком, к примеру, если использовать метод find(), то ошибка будет в строке 66 ,собственно, где и используется оператор.
Поэтому прошу помочь создать перегрузку оператора, заранее спасибо.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.12.2020, 15:34
Ответы с готовыми решениями:

Перегрузка оператора присваивания
мне надо было реализовать конструкторы, деструктор, оператор присваивания, функции ввода / вывода объектов; кто сможет дописать...

Перегрузка оператора присваивания
Здравствуйте, недавно читал про перегрузку операторов и решил поупражняться с этим, однако на практике возникла проблема. Ниже приведен код...

Перегрузка оператора присваивания
Добрый вечер. Есть задание: Нужно так перегрузить оператор =, чтобы можно было элементу одного класса, присваивать значение элемента...

17
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
23.12.2020, 15:39
Цитата Сообщение от 3aDr1K Посмотреть сообщение
Поэтому прошу помочь создать перегрузку оператора
а где класс данных, который ты передаешь в качестве аргумента шаблона? В нем и нужно перегрузить операцию присваивания.
0
0 / 0 / 0
Регистрация: 23.10.2019
Сообщений: 12
23.12.2020, 15: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
class Number
{
    friend ostream& operator<<(ostream& out, const Number& otherNumber);
    friend istream& operator>>(istream& in, Number& otherNumber);
private:
    int multiCount = 20;
    int Num_;
    void devide();
    int* ap_; //Указатель на массив множителей
public:
    Number(); 
    Number(int N);
    Number(const Number& otherNumber);
    ~Number();
    void show();
    void add(Number const& otherNumber);
    void subtract(Number const& otherNumber);
    void multiply(Number const& otherNumber);
    int compare(Number const& otherNumber) const;
    void setnewvalue(int N);
    Number operator+(Number otherNumber);
    Number operator-(Number otherNumber);
    Number operator*(Number otherNumber);
    Number& operator=(Number& otherNumber);
    bool operator>(const Number& otherNumber) const;
    bool operator<(const Number& otherNumber) const;
    bool operator==(const Number& otherNumber) const;
    bool operator!=(const Number& otherNumber) const;
};
Если я правильно вас понял
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
23.12.2020, 15:45
3aDr1K,
C++
1
2
3
4
5
6
Number & operator = (const Number & other)
{
    Number temp(other);     // Вся работа выполняется здесь
    Swap(temp);             // Здесь исключений не может быть
    return *this;
}
псевдокод
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 16:11
Цитата Сообщение от _stanislav Посмотреть сообщение
псевдокод
Идиома Саттера хороша для конструирования (копии), так как именно там возможен захват ресурсов и выброс исключения. Но для свопа нужен оператор присваивания. А тут нужно пройтись по полям (как говаривал один председатель колхоза).
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
23.12.2020, 16:14
Цитата Сообщение от IGPIGP Посмотреть сообщение
Идиома Саттера

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

3aDr1K, еще так можно:
C++
1
2
3
4
5
Number & operator=(Number temp)
{
    Swap(temp);
    return *this;
}
0
0 / 0 / 0
Регистрация: 23.10.2019
Сообщений: 12
23.12.2020, 17:06  [ТС]
Работает то работает, а при вызове метода, к примеру, remove(), всё равно не компилируется

Добавлено через 9 минут
Вернее, если в main() не вызывать методы, кроме add(), то программа запустится и приравнивание работает, но если попытаться вызвать, то не скомпилируется

Добавлено через 32 минуты
Всё заработало, проблема оказалась даже не операторе присваивания, а в названии поля
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 18:36
Цитата Сообщение от _stanislav Посмотреть сообщение
В каждой функции следует собрать весь код, который может генерировать исключения, и
выполнить его отдельно, безопасным с точки зрения исключений способом. Только после
этого, когда вы будете знать, что вся реальная работа успешно выполнена, вы можете из-
менять состояние программы (а также выполнять другие необходимые действия, например,
освобождение ресурсов) посредством операций, которые не генерируют исключений.
Так он и пишет. Но своп сам по себе требует оператора =. А если он есть, то на константной ссылке всё едино не скомпелируется. _stanislav, ладно. Чуть позже (пара часов), когда смогу добраться до ide и будет время - напишу ещё. Может я чего нафантазировал. Проверю.)
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
23.12.2020, 18:43
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но своп сам по себе требует оператора =.
зачем? его (Swap) же сам реализовываешь для своего класса как функцию член.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 19:03
Цитата Сообщение от _stanislav Посмотреть сообщение
зачем? его (Swap) же сам реализовываешь для своего класса как функцию член.
Покажи. Может ты станешь конструктора копий использовать для переустановки? Но Саттер именно этого и пытается избежать делая наоборот. Впрочем, - покажи.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
23.12.2020, 19:14
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
class Class
{
    // ...
public:
    void Swap(Class &) noexcept;
};
 
 
class SomeClass
{
    int i;
    double d;
    Class c;
 
    void Swap(SomeClass & r) noexcept
    {
        int ti;
        double td;
 
        ti = i;
        i = r.i;
        r.i = ti;
 
        td = d;
        d = r.d;
        r.d = td;
 
        c.Swap(r.c);
    }
};
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 19:51
_stanislav, дело даже не в том, что вы требуете от класса Class реализации члена Swap, хотя для отказа от std::swap нужны серьёзные основания. Я вижу проблему в том, что своп используется для реализации оператора = а не наоборот. Кроме того, приходится применять разные операции для разных полей без видимых оснований.

Добавлено через 4 минуты
Цитата Сообщение от 3aDr1K Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
template <typename T> typename List<T>::Node* List<T>::find(T i)
{
 Node* pv = pbeg;
 while (pv)
 {
 if (pv->data = data) break;
 pv = pv->next;
 }
 return pv;
}
попробуйте вместо data написать i. И параметр T i лучше бы const T &i
но лучше -наоборот - const T &data тогда меньше движений курсором и глаз не так режет)
тут и присваивание не виновато, похоже)
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.12.2020, 20:16
Цитата Сообщение от 3aDr1K Посмотреть сообщение
Вот весь код, связанный со списком, к примеру, если использовать метод find(), то ошибка будет в строке 66 ,собственно, где и используется оператор.
Цитата Сообщение от 3aDr1K Посмотреть сообщение
template <typename T> typename List<T>::Node* List<T>::find(T i)
find(const T &i)

Цитата Сообщение от 3aDr1K Посмотреть сообщение
if (pv->data = data) break;
if (pv->data == data)

if (pv->data == i) ?
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 20:18
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
pv->data == data
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
23.12.2020, 20:31
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но своп сам по себе требует оператора =
Требует, но ведь очень важно у чего.
Смотрите пример здесь.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 22:19
Цитата Сообщение от DrOffset Посмотреть сообщение
Требует, но ведь очень важно у чего.
Если поля swapable и реалbзован свой swap то можно и так. Спор о курице и яйце не имеет смысла. Я остаюсь при мнении, что оператор присваивания более универсален. А имея обе версии можно отдать std::swap право решать перемещать или копировать rvalue. А пример я перетащу сюда:
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 T {
    int *arr;
    size_t sz;
public:
    //.......
 
    T& operator = (const T& ref) {
        if (this != &ref)
        {
            T(ref).swap(*this);
        }
        return *this;
    }
 
    //......
 
private:
    void swap(T & t)
    {
        std::swap(arr, t.arr);
        std::swap(sz, t.sz);
    }
};
чтобы легче было тем кто читает. Я не спорю с тем, что если std::swap использован для полей, то можно и оператор присваивания реализовать на базе обмена (кроме полей, которые придётся самому как-то присвоить). Интересно почему тогда уж не принять по значению (предполагая наличие конструктора копии) и сделать нечто вроде:
C++
1
2
3
4
5
6
T& operator = (T val) {
       
            swap(val);
       
        return *this;
    }
?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
23.12.2020, 22:36
Цитата Сообщение от IGPIGP Посмотреть сообщение
Я не спорю с тем, что если std::swap использован для полей, то можно и оператор присваивания реализовать на базе обмена (кроме полей, которые придётся самому как-то присвоить).
Так ведь именно в этом и состоит идиома Саттера.

Цитата Сообщение от IGPIGP Посмотреть сообщение
сделать нечто вроде
Это вполне возможный и адекватный вариант.

Добавлено через 5 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
можно и оператор присваивания реализовать на базе обмена
Причем обмен тут идет под руку с конструктором копирования, вместе предоставляя безопасное с точки зрения исключений присваивание. Собственно идиома именно за этим и нужна, и практически больше ни за чем: код копирования объекта мы пишем один раз, в конструкторе копирования, в операторе присваивания мы обмениваем указатель-член. Если копирование с помощью конструктора во временный объект прошло успешно, без исключений, то простой обмен указателей безопасно поменяет состояние объекта, используя временный. Если во время копирования произошло исключение, то до swap дело не дойдет, объект останется в прежнем состоянии, не нарушив инварианта.

Добавлено через 2 минуты
Естественно идиома не применима, если у нас нет возможности организовать swap, который не бросает исключений. Никто, в первую очередь Саттер, не заявлял о серебряной пуле. Так что спорить тут не о чем. Нужно смотреть на границы применимости.
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
23.12.2020, 22:55
DrOffset, да, - вижу что был неправ. Спасибо)
_stanislav, пришёл DrOffset и победил меня. Я перепутал, извините. Конструктор копии принимающий по значению, это я сказанул. Сама передача значения - копирование. А по ссылке свопить аргумент уже нельзя. То есть ваш код вполне нормален. Простите.
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.12.2020, 22:55
Помогаю со студенческими работами здесь

Перегрузка оператора присваивания
MyArray&amp; operator=( MyArray &amp;arrInt2 ) //Зачем писать MyArray&amp; operator?А почему не MyArray operator ? { delete ...

Перегрузка оператора присваивания
Здравствуйте! Помогите, пожалуйста разобраться с перегрузкой оператора присваивания. Нужно написать класс матрица, в котором есть...

Перегрузка оператора присваивания
Доброго времени суток всем! Никак не могу правильно написать перегрузку оператора присваивания. При создании одного нового элемента...

Перегрузка оператора присваивания
Вот есть такой класс template&lt;typename TT&gt; class Matrix { public: ...

Перегрузка оператора присваивания
struct pointer_command { public: void * x; public: void set(void * y){x = y; } void operator = (void * y ) {x = y;} void*...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru