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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.80
cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
#1

Конструктор копирования(быстрый вопрос) - C++

28.11.2011, 02:09. Просмотров 1310. Ответов 28
Метки нет (Все метки)

Вроде бы все просто и логично, но в итоге выполнения B не копируется в A :C why?
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
#include <iostream>
 
using namespace std;
 
class Int {
    int a;
public:
    Int() {a = 0;}
    Int(int A)  {a = A;}
    int getA() const { return a; }
 
    Int& operator = (const Int &obj) {
        int a;
        a = obj.a;
        return *this;
    }
 
    Int(const Int& obj) {
        int a = 0;
        a = obj.a;
    }
 
};
 
int main () {
 
 
    Int A(1);
    Int B(A);
    cout << B.getA();//Ожидал увидеть 1, а получается что-то типа -8589......
        Int C(12);
        C = A;
        cout << C.getA();//Ожидал увидеть тоже 1, а получается 12, то есть значение не изменилось.
 
 
 
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.11.2011, 02:09
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Конструктор копирования(быстрый вопрос) (C++):

Не могу сделать чтобы класс содержал основной конструктор и конструктор копирования - C++
Разработать класс ThreeAngle для работы с плоскими треугольниками. В качестве членов-данных задаются длины трех сторон треугольника. Класс...

Не могу правильно сделать конструктор и конструктор копирования и принадлежность точки с заданными координатами треугольнику - C++
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; #include &lt;math.h&gt; #include &lt;algorithm&gt; using...

Конструктор инициализации, конструктор копирования, деструктор - C++
Я сделал почти задание по перегрузке операторов. Осталось одно, тоесть три: конструктор инициализации, конструктор копирования, деструктор....

Создать класс "Вектор" и реализовать конструктор по умолчанию, конструктор копирования и деструктор - C++
Всем доброго времени суток! нужна ваша помощь! нужно создать класс вектор и реализовать конструктор по умолчанию, копирования и...

Конструктор копирования - C++
Конструктор копирования в качестве параметра принимает ссылку на экземпляр типа класса. Вопрос заключается, почему именно...

Конструктор копирования - C++
Есть вопрос. Как объект одного класса передать в объект другого класса?

28
fom4ik
49 / 7 / 1
Регистрация: 07.11.2010
Сообщений: 52
28.11.2011, 02:12 #2
он должен возвращать новый созданный объект
0
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
28.11.2011, 02:14 #3
Цитата Сообщение от cetrael Посмотреть сообщение
Int(const Int& obj) {
int a = 0;
a = obj.a;
}
Намек ясен?
0
cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:14  [ТС] #4
Цитата Сообщение от fom4ik Посмотреть сообщение
он должен возвращать новый созданный объект
Кто он, какой объект? По-подробней, пожалуйста, все-таки ночь за окном )
0
Сыроежка
Заблокирован
28.11.2011, 02:15 #5
cetrael, У вас должно все копироваться. По крайней мере визуально я не вижу причин некорректной работы конструктора копирования.

Пардон, я уже устал. Вы создаете в своемконструкторе локальную переменную с тем же самым именем, что и член класса, Эта локальная переменная скрывает имя члена класса. Поэтому значение получает не член класса, а ваша локальная переменная.
0
cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:17  [ТС] #6
Каааак вы так быстро соображаете ночью?
Все большое спасибо, работа пошла в гору
0
Bers
Заблокирован
28.11.2011, 02:20 #7
Обратите внимание на этот код:
C++
1
2
3
4
5
6
Int(const Int& obj) {
 int a = 0; //здесь объявляется новая переменная
 a = obj.a; //этой новой переменной даётся значение
 }// по выходу из тела функции переменная уничтожается
//переменная данная-член остаётся без изменений
//вы уверены, что это именно то, что вы хотели?
0
cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:21  [ТС] #8
Цитата Сообщение от BRcr Посмотреть сообщение

Не по теме:


А можно грамотным языком услышать, что за бред я писал.
Получается я создавал ещё одну переменную, точно такую же, как в классе? Тогда почему не было неопределенности?
0
Сыроежка
Заблокирован
28.11.2011, 02:23 #9
Цитата Сообщение от cetrael Посмотреть сообщение
А можно грамотным языком услышать, что за бред я писал.
Получается я создавал ещё одну переменную, точно такую же, как в классе? Тогда почему не было неопределенности?
переменные во вложенных блоках скрывают переменные, объявленные во внешних блоках. Например,

C++
1
2
3
4
5
6
7
8
9
10
int i = 1;
 
int main()
{
   int i = 2;
   {
      int i = 3;
      for ( int i = 4; i > ::i; --i );
   }
}
0
Bers
Заблокирован
28.11.2011, 02:25 #10
Цитата Сообщение от cetrael Посмотреть сообщение
Тогда почему не было неопределенности?
новая переменная скрывала собой объявленную в классе

Можно например, написать так:
C++
1
2
3
4
Int(const Int& obj) {
        int a = 0;
       Int::a = obj.a; //разрешение контекста
    }
С помощью разрешения контекста можно явно указывать компилятору, какую именно "версию" данных вы имеете ввиду.
В данном случае получится, что локальная переменная инициализируется, но не используется.
А настоящий данный-член получит корректное значение
0
Сыроежка
Заблокирован
28.11.2011, 02:34 #11
Цитата Сообщение от Bers Посмотреть сообщение
новая переменная скрывала собой объявленную в классе

Можно например, написать так:
C++
1
2
3
4
Int(const Int& obj) {
        int a = 0;
       Int::a = obj.a; //разрешение контекста
    }
С помощью разрешения контекста можно явно указывать компилятору, какую именно "версию" данных вы имеете ввиду.
В данном случае получится, что локальная переменная инициализируется, но не используется.
А настоящий данный-член получит корректное значение
Что это за "разрешение контекста"? Такой синтаксис Int::a вы можете использовать только для статических членов класса. В данном же случае следовало записать this->a.

Добавлено через 3 минуты
Bers, Прошу извинения, вы правы. Можно внутри класса использовать такое квалифицированное имя.
0
Bers
Заблокирован
28.11.2011, 02:36 #12
Цитата Сообщение от Сыроежка Посмотреть сообщение
Что это за "разрешение контекста"? Такой синтаксис Int::a вы можете использовать только для статических членов класса. В данном же случае следовало записать this->a.
"разрешение контекста" указывает компилятору, какая версия данных должна быть использована.
Выше был пример для данных-членов.
Вот другой пример:

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
struct Base 
{
    void View() {std::cout<< "Base\n"; } 
};
 
struct Der: public Base 
{ 
    void View() 
    {
        std::cout<< "Der\n"; 
        Base::View(); //разрешение контекста указывает
                      //компилятору какую версию метода нужно запустить
                      //если забудите указать - получите рекурсию
    } 
};
 
 
int main()
{
 
    Der test;
    test.View();
    EndProgramm();
}
Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Bers, Прошу извинения, вы правы. Можно внутри класса использовать такое квалифицированное имя.
Ничего-ничего. Вы своими замечаниями частенько мне мозги прочищаете. Таки, только на пользу идёт)
0
greeezz
273 / 166 / 4
Регистрация: 10.07.2011
Сообщений: 441
28.11.2011, 03:54 #13
ваш класс я бы сделал как-то так:
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
#include <iostream>
 
using namespace std;
 
class Int {
public:
        Int(int b = 0){
            a = b;
        }
 
        int getInt() const {
            return a;
        }
 
        const Int &operator=(const Int &obj) {
            if(&obj != this){
                this->a = obj.a;
            }
                return *this;  //для выражений типа  x = y = z
        }
 
private:
        int a;
};
 
int main () {
        Int A(1);
        Int B(A);
        cout << "OBJECT B.getInt() : " <<B.getInt() << endl;
        Int C(12);
        cout << "OBJECT before assignment C.getInt() : " << C.getInt() << endl;
        C = A;
        cout << "OBJECT after assignment C.getInt() : " << C.getInt();
}
0
Сыроежка
Заблокирован
28.11.2011, 04:42 #14
Цитата Сообщение от greeezz Посмотреть сообщение
ваш класс я бы сделал как-то так:
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
#include <iostream>
 
using namespace std;
 
class Int {
public:
        Int(int b = 0){
            a = b;
        }
 
        int getInt() const {
            return a;
        }
 
        const Int &operator=(const Int &obj) {
            if(&obj != this){
                this->a = obj.a;
            }
                return *this;  //для выражений типа  x = y = z
        }
 
private:
        int a;
};
 
int main () {
        Int A(1);
        Int B(A);
        cout << "OBJECT B.getInt() : " <<B.getInt() << endl;
        Int C(12);
        cout << "OBJECT before assignment C.getInt() : " << C.getInt() << endl;
        C = A;
        cout << "OBJECT after assignment C.getInt() : " << C.getInt();
}
У вашей реализации имеется немало недостатков. Конструктор лучше писать следующим образом

C++
1
        Int( int a = 0 ) : x( a ) {}
то есть лучше задать список инициализации.

Функцию getInt лучше переименовать в getx или get_x. Дело в том, Int - это тип, и getInt звучит как получить тип, вместо того, чтобы получить значение члена объекта.

C++
1
        int getx() const { return ( x ); }
Не понятно почему оператор присваивания возвращает константную ссылку на объект. В С++ значением, возвращаемым оператором присваивания является lvalue, поэтому квалификатор const здесь не удел. То есть вместо вашего

C++
1
2
3
4
5
6
        const Int &operator=(const Int &obj) {
            if(&obj != this){
                this->a = obj.a;
            }
                return *this;  //для выражений типа  x = y = z
        }
следует написать

C++
1
2
3
4
5
        Int & operator =( const Int &obj )
        {
            x = obj.x;
              return ( *this );        }
        }
И нет необходимости делать проверку вида this != &obj.
На самом деле для этого класса ни конструктор копирования, ни копирующий оператор присваивания не требуются.
А что требуется, так как это перегрузка всех арифметических операторов, которые используются с целочисленными типами, а также операторы сравнения, битовые операторы и т.д.
0
greeezz
273 / 166 / 4
Регистрация: 10.07.2011
Сообщений: 441
28.11.2011, 05:47 #15
Сыроежка,

Не по теме:

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


теперь по теме.
Цитата Сообщение от Сыроежка Посмотреть сообщение
У вашей реализации имеется немало недостатков. Конструктор лучше писать следующим образом

C++
1
        Int( int a = 0 ) : x( a ) {}
то есть лучше задать список инициализации.
я не инициализирую константные переменные и по этому использование такого метода инициализации не панацея в данном примере.

Цитата Сообщение от Сыроежка Посмотреть сообщение
Функцию getInt лучше переименовать в getx или get_x. Дело в том, Int - это тип, и getInt звучит как получить тип, вместо того, чтобы получить значение члена объекта.

C++
1
        int getx() const { return ( x ); }
совершенно согласен.
Цитата Сообщение от Сыроежка Посмотреть сообщение
Не понятно почему оператор присваивания возвращает константную ссылку на объект. В С++ значением, возвращаемым оператором присваивания является lvalue, поэтому квалификатор const здесь не удел. То есть вместо вашего
const нужен чтобы избежать инцидентов вот такого характера : (A = B) = C;


Цитата Сообщение от Сыроежка Посмотреть сообщение
И нет необходимости делать проверку вида this != &obj.
как раз дело в том что нет необходимости присваивать значения полей объекта к ним же самим

Цитата Сообщение от Сыроежка Посмотреть сообщение
А что требуется, так как это перегрузка всех арифметических операторов, которые используются с целочисленными типами, а также операторы сравнения, битовые операторы и т.д.
Это где автор темы такое написал?
Я привел пример реализации класса на основе того что нужно было автору. Если попросит помочь с перегрузкой других операторов. будем делать другие примеры.
0
28.11.2011, 05:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.11.2011, 05:47
Привет! Вот еще темы с ответами:

Конструктор копирования - C++
Доброго времени суток! Написала класс Треугольная матрица. Не могу исправит такую вот ошибку: ОС Windows инициировала точку останова...

Конструктор копирования - C++
Ответьте пожалуйста какой необходим конструктор копирования для объекта класса который передается в функцию?

конструктор копирования - C++
не могу понять, почему не срабатывает конструктор копирования. #include &lt;iostream&gt; using namespace std; class Shape { ...

Конструктор копирования - C++
Помогите пожалуйста разобраться, необходимо добавить конструктор копирования, теорию знаю, а как на практике применить не знаю. Программа...


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

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

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