Форум программистов, компьютерный форум CyberForum.ru

оператор присваивания - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.87
Lotles
 Аватар для Lotles
1 / 1 / 0
Регистрация: 29.12.2009
Сообщений: 167
11.10.2010, 21:10     оператор присваивания #1
Привет всем !
Каким образом вызывается оператор присваивания, например, здесь:
Код
a = "I ";
если в аргументе char*, а в операторе присваивания const String&.
Может быть дело в operator char*(), но в ответе operator char() вызывается после присваивания:

Компилятор выводит :
Vizivaetsja operator prisvaivanija
Vizivaetsja operator prisvaivanija
Vizivaetsja operator prisvaivanija
Vizvalsja operator char*
...
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
#include "stdafx.h"
#include "conio.h"
#include <string.h>
using namespace std;
int a;
class String {
private:
    char* ptr;
public:
    String(){
        ptr = new char[1];
        ptr[0] = '\0';
    }
    String(char* s){
            int n = strlen(s);
            ptr = new char[n + 1];
            strcpy(ptr, s);
    }
    String(const String& src){
            int n = strlen(src.ptr);
            ptr = new char[n + 1];
            strcpy(ptr, src.ptr);
    }
 
    ~String(){
            delete [] ptr;
    }
 
    String& operator=(const String& src){
        cout << "Vizivaetsja operator prisvaivanija" << endl;
        cpy(src.ptr); 
        return *this;
    }
 
 
 
    String operator+(char* s){
        String new_str(ptr);
            cout << "S = " << s << endl;
            cout << "new_str.ptr = " << new_str.ptr << endl;
            cout << "ptr = " << ptr << endl;
            new_str.cat(s);
            return new_str;
    }
    operator char*() {
        cout << "vizvalsja operator char*" << endl;
        cout << "ptr = " << ptr << endl;
        return ptr;
    }
    void cat(char* s){
            int n = strlen(ptr) + strlen(s);
            cout <<".......... " << ptr << endl;
            cout <<".......... " << s << endl;
            char* p1 = new char[n + 1];
            strcpy(p1, ptr);
            strcat(p1, s);
            delete [] ptr;
            ptr = p1;
    }
    void cpy(char* s){
        delete [] ptr;
        int n = strlen(s);
        ptr = new char[n + 1];
        strcpy(ptr, s);
    }
};
 
int main() {
    String a, b, c;
    a = "I ";
    b = "am ";
    c = "so ";
    String d = a + b;
    cout << d << endl;
    return 0;}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.10.2010, 21:10     оператор присваивания
Посмотрите здесь:

C++ Оператор присваивания и деструктор
Оператор присваивания C++
C++ оператор присваивания
Оператор присваивания. C++
Оператор присваивания в c++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Andrew_Lvov
Эксперт C++
 Аватар для Andrew_Lvov
259 / 189 / 5
Регистрация: 19.08.2010
Сообщений: 758
Записей в блоге: 1
11.10.2010, 21:24     оператор присваивания #2
Вызывается неявно конструктор String( const char* ), потом копирование двух String'ов.
Lotles
 Аватар для Lotles
1 / 1 / 0
Регистрация: 29.12.2009
Сообщений: 167
12.10.2010, 02:42  [ТС]     оператор присваивания #3
Цитата Сообщение от Andrew_Lvov Посмотреть сообщение
Вызывается неявно конструктор String( const char* ), потом копирование двух String'ов.
Прошу, если пишите, пишите подробней

Добавлено через 4 часа 5 минут
C++
1
2
3
4
5
    String& operator=(const String& src){
                cout << "Vizivaetsja operator prisvaivanija" << endl;
                cpy(src.ptr); 
                return *this;
        }
Сюда, в src передается временный объект, созданный конструктором
C++
1
 String( const char* )
Так ?
Lotles
 Аватар для Lotles
1 / 1 / 0
Регистрация: 29.12.2009
Сообщений: 167
31.10.2010, 08:58  [ТС]     оператор присваивания #4
Почему в коде ниже вызывается конструктор копирования, а не оператор присваивания
Вообще есть правило, что если идет присваивание к уже существуемому объекту, то должен вызываться оператор присваивания
пр
C++
1
2
Fraction f4
f4=f1+f2+f3
иначе
C++
1
Fraction f4 = f1+f2+F3
вызывается конструктор копирования
Теперь у меня возникает проблема, если следовать этом правилам, то почему у здесь
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
#include <stdafx.h>
#include <conio.h>
#include "Fraction.h"
using namespace std;
class FloatFraction : public Fraction {
public:
    FloatFraction(){
        set(0,1);
    }
    FloatFraction(int n, int d){
            set(n,d);
    }
    FloatFraction(int n){
        set(n,1);
    }
    FloatFraction(const Fraction& src){
        set(src.get_num(), src.get_den());
    }
    FloatFraction(const FloatFraction& src){
        set(src.get_num(), src.get_den());
    }
    double get_float() {
    return static_cast<double>(get_num())/get_den();
     }
};
int main() {
    FloatFraction f1(1,2),f2(1,3),f3;
    f3=f1+f2;
    cout << "Value of f3 is " << f3 << endl;
    cout << "Float value of f3 is " << f3.get_float() << endl;
    return 0;
}
вызывается не оператор присваивания, а конструктор копирования ?
Если нужен код Fraction.h вот он
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
#include "stdafx.h"
#include "conio.h"
using namespace std;
class Fraction{
private:
    int num, den;
    void normalize(){
        if (den == 0 || num == 0) {
        num = 0;
        den = 1;
        }
    }
    int gcf(int a, int b){
        if (a % b == 0)
        return abs(b);
    else
        return gcf(b, a % b);
    }
    int lcm(int a, int b){
        return (a/gcf(a,b)*b);
    }
public:
    Fraction(){
        set(0, 1);
    }
    Fraction(int n, int d){
        set(n, d);
    }
    Fraction(int n){
        set(n,1);
    }
    Fraction(const Fraction& src){
        set(src.num,src.den);
    }
    void set(int n, int d){
        num = n; den = d; normalize();
    }
    int get_num() const{
        return num;
    }
    int get_den() const{
        return den;
    }
    Fraction add(const Fraction& other){
        Fraction fract;
    int lcd = lcm(den, other.den);
    int quot1 = lcd/den;
    int quot2 = lcd/other.den;
    fract.set(num * quot1 + other.num * quot2, lcd);
    fract.normalize();
    return fract;
    }
    Fraction mult(const Fraction& other){
        Fraction fract;
    fract.set(num * other.num, den * other.den);
    fract.normalize();
    return fract;
    }
    Fraction operator+(const Fraction& other){
        return add(other);
        }
    Fraction operator=(const Fraction& src){
        set(src.num, src.den);
        return *this;
    }
    Fraction operator*(const Fraction& other){
        return mult(other);
    }   
    friend ostream& operator << (ostream& os, Fraction& fr){
        os << fr.num << "/" << fr.den;
        return os;
    }
};
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,268
31.10.2010, 13:15     оператор присваивания #5
Давай с последним примером разбираться, я щас над ним тоже парюсь, у меня вопросы похожие.
1) Почему вызывается не оператор присваивания

Ты наверное, имеешь ввиду этот код
C++
1
f1= f2+ f3
Ну я так понял, оператр присваивания нигде у тебя не определён, но тем не менее, он вызывается ВСЁ-ТАКИ, просто вызова мы не видим. Но тем не менее. У меня в книге написано по этому поводу:

"Функция оператора присваивания является специальной функцией, потому что компилятор сам её подставляет, если вы не делаете этого"

Ну вроде пока всё понятно должно быть. Уточняй если что не так.

2) К тому же конструктор копирования действительно вызывается. Ты имеешь ввиду этот?
C++
1
2
3
FloatFraction(const FloatFraction& src){
        set(src.get_num(), src.get_den());
    }
Ну, а почему бы ему не вызываться? ЕСли ты имеешь ввиду тот же самый код, то н приодится к такому виду:

C++
1
f1= f2.add(f3)
Теперь смотрим, что написано в книге:
ситуации, когда вызывается конструктор копирования АВТОМАТИЧЕСКИ, то есть ты не прописываешь его вызов, а н вызывается
1) Когда возвращаемое значение имеет тип класса

и так далее

В даном случае add возвращает переменную типа Fraction, поэтому конструктор копирования всё-таки вызывается (и должен вызываться), хоть мы этого и не видим (автоматически то есть)

Ну как-то так. Коряво.

Добавлено через 3 минуты
А, не я соврал чуток. Ты же не пишешь какой именно код ты имеешь ввиду приходится додумывать самому
Итак. f3= f1+ f2

При возвращении add значения вызывается (наверное) вот это конструктор копирования:
C++
1
2
3
FloatFraction(const Fraction& src){
        set(src.get_num(), src.get_den());
    }
А не тот, о котором я писал вначале

Добавлено через 2 часа 29 минут
Но что действительно удивляет, так это почему не вызывается это конструктор копирования
C++
1
2
3
    FloatFraction(const FloatFraction& src){
        set(src.get_num(), src.get_den());
    }
В этом выражении
C++
1
f3 = f1 + f2;
Оно ведь приводится к виду:
C++
1
   f3 = f1.add(f2);
Должен выщзываться констуктор копированя! Вот в книге написано:
"Конструктор копирования вызывается, когда аргумент имеет тип класса"

Это и есть тот случай
Аргумент тут f2, он имеетр тип FloatFraction, а, посколку add с таким классом работать не может,
его надо привести к типу Fraction

Вот и должен автоматом вышеупомянутый конструктор вызываться. Так не вызывается! Пишем так:

C++
1
2
3
4
    FloatFraction(const FloatFraction &src) {
     printf ("ttttttttttttttt\n");
     set(src.get_num(), src.get_den());
    }
Компилим, запускаем код на исплнение и ждём появления троки "ttttttttttttttttt\n". ТАк ведь нет её
В чём дело, друзья?
Lotles
 Аватар для Lotles
1 / 1 / 0
Регистрация: 29.12.2009
Сообщений: 167
31.10.2010, 16:20  [ТС]     оператор присваивания #6
Принцип работы:
C++
1
f3=f1+f2;
1) После сложения add возвращает Fraction, вызывается
C++
1
2
3
    Fraction(const Fraction& src){
        set(src.num,src.den);
    }
2) Неявно вызывается
C++
1
2
3
4
Fraction operator=(const Fraction& src){
        set(src.num, src.den);
        return *this;
}
3) т.к operator= возвратил Fraction, а f3 - ProperFraction, то вызывается
C++
1
2
3
    ProperFraction(const Fraction& src){
        set(src.Fraction::get_num(), src.get_den());
    }
чтобы f3.num и f3.den присвоить значения

Добавлено через 10 минут
Вот и должен автоматом вышеупомянутый конструктор вызываться. Так не вызывается! Пишем так:
FloatFraction(const FloatFraction &src) {
printf ("ttttttttttttttt\n");
set(src.get_num(), src.get_den());
}
вы перепутали, не FloatFraction, а ProperFraction
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,268
31.10.2010, 16:29     оператор присваивания #7
Ты описал пункт 1, 2 и 3. Я предлагаю обратиться к пункту 0 или даже -1

...Что происходит ДО выполнения этих трёх пунктов? Много чего. Но меня интересует
f3=f1.add(f2)

Ты ведь согласишься, что f1=f2+ f3 подменяется f3=f1.add(f2)?

А теперь смотри, итак add(f2)
В функцию add передаётся параметром объект f2.

Вопрос: должен ПРИ ЭТОМ вызываться конструктор копирования?
Ответ: да должен. За доказательсвтом лезем в книгу и читаем:
"Ниже представлены ситуации, в которых конструктор копирования вызывается автоматически:
1) ПРопускаем эту ситуацию
2) Когда аргумент имеет тип класса. Создаётся копия аргумента и затем передаётся в функцию"

Второй пункт это наша ситуация. Я хочу воочию убедиться, что конструктор копирования действительно вызван.

Для этого я задаюсь вопросом: а какой именно конструктор копирования? А вот этот:
C++
1
2
3
    FloatFraction(const FloatFraction &src) {
     set(src.get_num(), src.get_den());
    }
Ведь посмотри,
1) у него принимаемый аргумент имеет тип const FloatFraction &src (это соответствет f2

2) Этот конструктор "принадлежит" классу FloatFraction. Это как раз наша ситуация, ведь вся эта херь add(f2) "принадлежит" объекту класса FloatFraction- объекту f1. Действительно: f3=f1.add(f2)

Ну то есть есть все основания, что ПРЕЖДЕ ЧЕМ выполнятся пункты, о которых ты сказал, вызовется вышеупомянутый конструктор копирования.
Для того, чтобы в этом убедиться, как я уже сказал, пишем так:
C++
1
2
3
4
    FloatFraction(const FloatFraction &src) {
     printf ("ttttttttttttttt\n");
     set(src.get_num(), src.get_den());
    }
Ну и всё. Сидим, ждём появления строчки "ttttttttttttttttt". А её нет.
Где ошибка в рассуждениях?

Добавлено через 3 минуты
Цитата Сообщение от Lotles Посмотреть сообщение
вы перепутали, не FloatFraction, а ProperFraction
Так не пойдёт, я ничё не перепутал. Смотри свой первый код, там и намёка нет на ProperFraction
Lotles
 Аватар для Lotles
1 / 1 / 0
Регистрация: 29.12.2009
Сообщений: 167
31.10.2010, 17:24  [ТС]     оператор присваивания #8
C++
1
2
3
Fraction operator+(const Fraction& other){
        return add(other);
        }
other - ссылка
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,268
31.10.2010, 17:58     оператор присваивания #9
Разве это имеет значение? Не знаю. Постараюсь исходить из сухих тык скыть фактов и опровергнуть сей аргумент

Во-первых, я уже приводил цитату из книги, согласно которой конструктор копирования ДОЛЖЕН вызываться в этом случае

Во-вторых (этого я не говорил) далее в книге читаем:
"Синтаксис для объявления конструктора следующий
имя_класса (имя_класса const &источник)"

То есть в качестве образца мы видим передачу именно ССЫЛКИ. Как ни крути, а аргумент, что раз ссылка, то конструктор вызываться не должен, не канает

НАколнец, третье. Там есть ещё конструктор копирования. Вот он:
C++
1
2
3
    FloatFraction(const Fraction &src) {
     set(src.get_num(), src.get_den());
    }
Видишь? ТОже в качетве аргумента ссылка. Но он вызывается почему-то. ПРоверяется легко. Пишется Так:
C++
1
2
3
4
    FloatFraction(const Fraction &src) {
     set(src.get_num(), src.get_den());
     printf ("zzzzzzzzz\n");
    }
И наблюдается строка "zzzzzzzzzzzz\n"
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
13.12.2012, 09:41     оператор присваивания #10
Разве это имеет значение? Не знаю. Постараюсь исходить из сухих тык скыть фактов и опровергнуть сей аргумент
почитай про ссылки), когда в качестве аргумента передается ссылка на объект - объект не копируется)
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
13.12.2012, 10:54     оператор присваивания #11
вызывается не оператор присваивания, а конструктор копирования ?
Оператор присваивания вызывается. А почему вдруг не должен вызываться конструктор копии?
C++
1
2
3
    Fraction operator+(const Fraction& other){
        return add(other);
        }
Возвращает по значению, в итоге, если не учитывать RVO - вернет копию значения, возвращенного из функции add.
C++
1
Fraction add(const Fraction& other)
Опять же копию.
Итог: Вызов двух конструкторов копирования очевидным образом.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,268
13.12.2012, 11:05     оператор присваивания #12
Я разобрался давно уж вроде. Вывод: использование ссылки это по факту работа с указателем, но без синтаксиса указателя. Как в учебнике и написано.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.12.2012, 16:39     оператор присваивания
Еще ссылки по теме:

Оператор присваивания C++
Оператор присваивания C++
Перегруженный оператор присваивания C++

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

Или воспользуйтесь поиском по форуму:
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
13.12.2012, 16:39     оператор присваивания #13
Ссылка это альтернативное имя объекта, по которому можно к нему обращаться, и ссылка всегда инициализирована - другого не допустит компилятор, за исключением некоторых ситуаций, вызванных как раз таки не верныой работой с сылками)
Yandex
Объявления
13.12.2012, 16:39     оператор присваивания
Ответ Создать тему
Опции темы

Текущее время: 19:17. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru