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

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

Войти
Регистрация
Восстановить пароль
 
 
Адренс Аксидор
5 / 5 / 1
Регистрация: 16.05.2012
Сообщений: 92
#1

Класс со значением полей "по умолчанию" - C++

11.11.2013, 10:35. Просмотров 1087. Ответов 26
Метки нет (Все метки)

Здравствуйте. Написал программу, но не могу сделать так, чтобы класс принимал значение полей по умолчанию - закомментированный вариант вызывает ошибку. Пожалуйста помогите исправить. И, если не сложно, объясните разницу между test,test2 и test3, а то в первом 2 вызова деструктора, во втором - один, а в третьем случае деструктор не вызывается


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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <iostream>
using namespace std;
//Класс Студент
class TStudent
{
private:
    char *LastName; 
    char *FirstName; 
    char *Patronimyc;
    int Born;
    char *Group; 
 
public:
    TStudent();//char *LastName, char *FirstName, char *Patronimyc, char *Group, int Born); //Конструктор класса по умолчанию *просто выделим память под все поля
    
    ~TStudent(); //Деструтор класса
    TStudent (TStudent& Student); //Конструктор копирования по умолчанию
    TStudent operator= (TStudent& Student); //Оператор присвоения
    TStudent test(TStudent s);
    void SetLastName (char* sLastName);  //Присваивание Фамилии
    void SetFirstName (char* sFirstName);//Присваивание Имени
    void SetPatronimyc (char* sPatronimyc);//Приваивание отчества
    void SetGroup(char* sGroup);
 
    char* GetLastName(void); //Получение указателя на Фамилию
    char* GetFirstName(void);//Получение указателя на имя
    char* GetPatronimyc(void); //Получение указателя на Отчество
    int& BornDate(void); //Изменение даты рождения
    char* GetGroup(void);
    //Дружественная функция перезагрузки вывода в стандартный поток вывода (STDOUT)
    friend ostream& operator<< (ostream& out, TStudent Student)
    {
        out<<"Фамилия : "<< Student.LastName<< endl;
        out<<"Имя : "<< Student.FirstName<< endl;
        out<<"Отчество : "<< Student.Patronimyc<< endl;
         out<<"Группа : "<< Student.Group<< endl;
        out<<"Год рождения : "<< Student.Born<< endl<< endl;
        
        return out;
    }
 
};
//Конструктор по умолчанию *просто выделим память под все поля
TStudent::TStudent()//char *LastName, char *FirstName, char *Patronimyc, char *Group, int Born)
{     cout << "Вызов конструктора" << endl;
    //Выделим памяти для Фамилии, Имени и Отчества на которые указывают их указатели char*
    LastName = new char[];
       FirstName = new char[];
        Patronimyc = new char[];
     Group = new char[];
   };
//Конструктор копирования по-умолчанию
TStudent::TStudent (TStudent& Student)
{
    //В конструкторе копирования, так же выделим память на которые указывают указатели
    LastName = new char[]; 
    FirstName = new char[];
    Patronimyc = new char[];
     Group = new char[];
   
    //И скопируем в них значения из объекта класса на базе которого мы создаем объект путем копирования
   LastName=strdup(Student.LastName);
   FirstName =strdup(Student.FirstName);
    Patronimyc =strdup(Student.Patronimyc);
     Group = strdup(Student.Group);
     Born = Student.Born;
}
//Перезагрузка оператора присвоения 
TStudent TStudent::operator= (TStudent& Student) //Оператор присвоения
{
     LastName=strdup(Student.LastName);
   FirstName =strdup(Student.FirstName);
    Patronimyc =strdup(Student.Patronimyc);
     Group = strdup(Student.Group);
     Born = Student.Born;
    return *this;
}
 
//Присваивание Фамилии
void TStudent::SetLastName (char* sLastName)
{
    strcpy(LastName,sLastName); 
}
 
//Присваивание Имени
void TStudent::SetFirstName (char* sFirstName)
{
    strcpy(FirstName,sFirstName); 
}
 
//Присваивание отчества
void TStudent::SetPatronimyc (char* sPatronimyc)
{
    strcpy(Patronimyc, sPatronimyc); 
}
 
//Присваивание Группы
void TStudent::SetGroup (char* sGroup)
{
    strcpy(Group, sGroup); 
}
 
 
 
 
//Получение указателя на Фамилию
char* TStudent::GetLastName(void) 
{                                 
    return LastName;        }      
 
//Получение указателя на имя
char* TStudent::GetFirstName(void)  //Аналогично прошлой
{
    return FirstName;
}
 
//Получение указателя на Отчество
char* TStudent::GetPatronimyc(void)  //Так же аналогично
{
    return Patronimyc;
}
 
//Получение указателя на group
char* TStudent::GetGroup(void)  //Так же аналогично
{
    return Group;
}
 
 
 
 
//Возврат ссылки на дату рождения
int& TStudent::BornDate(void) //Возвращаем ссылку на ДатуРождения 
{
    return Born;
}
 
//Деструктор класса
 
TStudent::~TStudent()
{   cout << "Вызов деструктора" << endl;
    delete[] LastName; //Отчистим память которую мы выделили
    delete[] FirstName;//Отчистим память которую мы выделили
    delete[] Patronimyc;//Отчистим память которую мы выделили
    delete[] Group;//Отчистим память которую мы выделили
}
TStudent test(TStudent s){return s;}
TStudent test2 (TStudent &s){return s;}
TStudent& test3 (TStudent &s){return s;}
//Точка входа (главная функция)
void main(void)
{ char f[40], n[40], p[40], g[40];
int b;
    setlocale(LC_ALL,"Russian");
    cout<<"Вход ф-ции main :"<< endl;
    TStudent D1; //Создади объект класса конструктором по умолчанию
    //Заполним его
    cin >> f >> n >> p >> g >> b;
    D1.SetFirstName(n);
    D1.SetLastName(f);
    D1.SetPatronimyc(p);
    D1.SetGroup(g);
    D1.BornDate() = b;
    cout<< D1; //Выведим на экран 
 
    //Создадим объект констуктором копирования
    TStudent D2(D1);
    //Если все было реализованно верно, то указатели D2 не должны быть равны указателям D1
    //Проверим это следующим образом
    cout<<"Проверка конструктора копирования по умолчанию, путем замены первой буквы фамилии на 'F':"<< endl;
        
    D2.GetLastName()[0] ='F';//Изменим первый символ фамилии D1 на 'F'
     cout << D2; //Выведим на экран сначало D1 и D2 (результаты должны быть разными
    test(D1);  // 2 раза вызывается деструктор
    test2(D1);  // 1 раз
    test3(D1);  // деструктор не вызывается
    cout<<"Выход из ф-ции main :"<< endl;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.11.2013, 10:35     Класс со значением полей "по умолчанию"
Посмотрите здесь:

Исправить ошибку "Левый операнд должен быть левосторонним значением" - C++
if(f) { fprintf(f,&quot;%d&quot;,l); for(i=0;i&lt;=h;i++) if(j&gt;n || str=&quot;.&quot;) { fprintf(f,&quot;%c&quot;,'\n'); j=0; ...

Выдает ошибку "выражение должно быть допустимым левосторонним значением" - C++
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; using namespace std; int main() { int f; int x; int b,a,c; cout &lt;&lt; &quot;Введите...

"Выражение должно быть допустимым для изменения левосторонним значением" - C++
#include &lt;iostream&gt; #include&lt;conio.h&gt; #include&lt;math.h&gt; #include&lt;fstream&gt; using namespace std; struct knigi { char name; ...

Конструктор Шредингера "нет подходящего конструктора по умолчанию", хотя он есть - C++
собственно, код. на 156-й строке ( cont(circi);) ругается на отсутствие конструктора в классе. но он там есть! я его видел! а если...

Ошибка: "Выражение должно быть допустимым для изменения левосторонним значением" - C++
struct statistica{ char name; double number1; // Номер счета double number2; // Приход double number3; // Расход char...

Ошибка "выражение должно быть допустимым для изменения левосторонним значением" - C++
В файле, путь к которому вводится с экрана, находится массив. #include &quot;stdafx.h&quot; #include &lt;iostream&gt; using namespace std; ...

Для структуры "Дата" реализовать конструктор по умолчанию, выводящий текущую дату - C++
Преподаватель дал задние,чтобы в структуре Date был конструктор по умолчанию.который выводит текущую дату.сказал что для этого туда надо...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Extrim88
50 / 50 / 11
Регистрация: 08.02.2013
Сообщений: 189
11.11.2013, 13:39     Класс со значением полей "по умолчанию" #21
Цитата Сообщение от Tulosba Посмотреть сообщение
Совершенно не обязательно. В теле конструктора для членов можно добавлять this->, а в инициализаторе конструктора можно и без этого обойтись.
Хорошо, такой пример, у меня есть класс с элементами данных
C++
1
double length; double width;
Определяем конструктор:
C++
1
2
3
4
5
Class_Name::Class_Name(double length, double length)
{
length = length;
width = width;
}
Не возникнет ли в таком случае неопределенности при инициализации элементов данных? Параметры конструктора не являются переменными-членами класса, они представляют значения, которые присваиваются переменным-членам.

Добавлено через 36 секунд
Class_Name::Class_Name(double length, double width)
{
length = length;
width = width;
}

Добавлено через 1 минуту
такой вариант, в первом варианте второй параметр неправильно назвал

Добавлено через 6 минут
это я не от "балды" придумал и совершенно ни к кому не придираюсь, просто сейчас специально открыл хорошую книжку С.Прата "Язык С++. Лекции и упражнения", читал когда-то, и там вспомнилась такая выноска касательно именования параметров в конструкторе
Цитата Сообщение от Extrim88 Посмотреть сообщение
Параметры конструктора не являются переменными-членами класса, они представляют значения, которые присваиваются переменным-членам.
Собственно цитата оттуда
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
11.11.2013, 13:51     Класс со значением полей "по умолчанию" #22
Цитата Сообщение от Extrim88 Посмотреть сообщение
Не возникнет ли в таком случае неопределенности при инициализации элементов данных?
Неопределенности нет. В данном случае поля не будут проинициализированы вовсе. Нужно писать:
C++
1
this->length = length;
Или использовать инициализатор конструктора:
C++
1
Class_Name::Class_Name(double length, double width) : length(length), width(width) {}
Extrim88
50 / 50 / 11
Регистрация: 08.02.2013
Сообщений: 189
11.11.2013, 13:52     Класс со значением полей "по умолчанию" #23
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <iostream>
using namespace std;
//Класс Студент
class TStudent
{
private:
    char *LastName; 
    char *FirstName; 
    char *Patronimyc;
    int Born;
    char *Group; 
 
public:
    TStudent(char* last = "Petr", char* first = "Petrov", char* patr = "Petrovich", char* gr = "abc123", int bo = 25); *Group, int Born); //Конструктор класса по умолчанию *просто выделим память под все поля
    
    ~TStudent(); //Деструктор класса
    TStudent (const TStudent& Student); //Конструктор копирования по умолчанию
    TStudent operator= (const TStudent& Student); //Оператор присвоения
    TStudent test(const TStudent& s);
    void SetLastName (char* sLastName);  //Присваивание Фамилии
    void SetFirstName (char* sFirstName);//Присваивание Имени
    void SetPatronimyc (char* sPatronimyc);//Приваивание отчества
    void SetGroup(char* sGroup);
 
    char* GetLastName(); //Получение указателя на Фамилию
    char* GetFirstName();//Получение указателя на имя
    char* GetPatronimyc(); //Получение указателя на Отчество
    int& BornDate(); //Изменение даты рождения
    char* GetGroup();
    //Дружественная функция перезагрузки вывода в стандартный поток вывода (STDOUT)
    friend ostream& operator<< (ostream& out, const TStudent& Student)
    {
        out<<"Фамилия : "<< Student.LastName<< endl;
        out<<"Имя : "<< Student.FirstName<< endl;
        out<<"Отчество : "<< Student.Patronimyc<< endl;
         out<<"Группа : "<< Student.Group<< endl;
        out<<"Год рождения : "<< Student.Born<< endl<< endl;
        
        return out;
    }
 
};
//Конструктор по умолчанию *просто выделим память под все поля
TStudent::TStudent(char* last, char* first, char* patr, char* gr, int bo)
{     cout << "Вызов конструктора" << endl;
    //Выделим памяти для Фамилии, Имени и Отчества на которые указывают их указатели char*
    LastName = new char[strlen(last) + 1];
       FirstName = new char[strlen(first) + 1];
        Patronimyc = new char[strlen(patr) + 1];
     Group = new char[strlen(gr) + 1];
 
 
   };
//Конструктор копирования по-умолчанию
TStudent::TStudent (TStudent& Student)
{
    //В конструкторе копирования, так же выделим память на которые указывают указатели
    LastName = new char[]; 
    FirstName = new char[];
    Patronimyc = new char[];
     Group = new char[];
   
    //И скопируем в них значения из объекта класса на базе которого мы создаем объект путем копирования
   LastName=strdup(Student.LastName);
   FirstName =strdup(Student.FirstName);
    Patronimyc =strdup(Student.Patronimyc);
     Group = strdup(Student.Group);
     Born = Student.Born;
}
//Перезагрузка оператора присвоения 
TStudent TStudent::operator= (TStudent& Student) //Оператор присвоения
{
     LastName=strdup(Student.LastName);
   FirstName =strdup(Student.FirstName);
    Patronimyc =strdup(Student.Patronimyc);
     Group = strdup(Student.Group);
     Born = Student.Born;
    return *this;
}
 
//Присваивание Фамилии
void TStudent::SetLastName (char* sLastName)
{
    strcpy(LastName,sLastName); 
}
 
//Присваивание Имени
void TStudent::SetFirstName (char* sFirstName)
{
    strcpy(FirstName,sFirstName); 
}
 
//Присваивание отчества
void TStudent::SetPatronimyc (char* sPatronimyc)
{
    strcpy(Patronimyc, sPatronimyc); 
}
 
//Присваивание Группы
void TStudent::SetGroup (char* sGroup)
{
    strcpy(Group, sGroup); 
}
 
 
 
 
//Получение указателя на Фамилию
char* TStudent::GetLastName(void) 
{                                 
    return LastName;        }      
 
//Получение указателя на имя
char* TStudent::GetFirstName(void)  //Аналогично прошлой
{
    return FirstName;
}
 
//Получение указателя на Отчество
char* TStudent::GetPatronimyc(void)  //Так же аналогично
{
    return Patronimyc;
}
 
//Получение указателя на group
char* TStudent::GetGroup(void)  //Так же аналогично
{
    return Group;
}
 
 
 
 
//Возврат ссылки на дату рождения
int& TStudent::BornDate(void) //Возвращаем ссылку на ДатуРождения 
{
    return Born;
}
 
//Деструктор класса
 
TStudent::~TStudent()
{   cout << "Вызов деструктора" << endl;
    delete[] LastName; //Отчистим память которую мы выделили
    delete[] FirstName;//Отчистим память которую мы выделили
    delete[] Patronimyc;//Отчистим память которую мы выделили
    delete[] Group;//Отчистим память которую мы выделили
}
TStudent test(TStudent s){return s;}
TStudent test2 (TStudent &s){return s;}
TStudent& test3 (TStudent &s){return s;}
//Точка входа (главная функция)
void main(void)
{ char f[40], n[40], p[40], g[40];
int b;
    setlocale(LC_ALL,"Russian");
    cout<<"Вход ф-ции main :"<< endl;
    TStudent D1; //Создади объект класса конструктором по умолчанию
    //Заполним его
    cin >> f >> n >> p >> g >> b;
    D1.SetFirstName(n);
    D1.SetLastName(f);
    D1.SetPatronimyc(p);
    D1.SetGroup(g);
    D1.BornDate() = b;
    cout<< D1; //Выведим на экран 
 
    //Создадим объект констуктором копирования
    TStudent D2(D1);
    //Если все было реализованно верно, то указатели D2 не должны быть равны указателям D1
    //Проверим это следующим образом
    cout<<"Проверка конструктора копирования по умолчанию, путем замены первой буквы фамилии на 'F':"<< endl;
        
    D2.GetLastName()[0] ='F';//Изменим первый символ фамилии D1 на 'F'
     cout << D2; //Выведим на экран сначало D1 и D2 (результаты должны быть разными
    test(D1);  // 2 раза вызывается деструктор
    test2(D1);  // 1 раз
    test3(D1);  // деструктор не вызывается
    cout<<"Выход из ф-ции main :"<< endl;
}
Адренс Аксидор
5 / 5 / 1
Регистрация: 16.05.2012
Сообщений: 92
11.11.2013, 14:03  [ТС]     Класс со значением полей "по умолчанию" #24
Возникают ошибки в 56 и 78 строках
Extrim88
50 / 50 / 11
Регистрация: 08.02.2013
Сообщений: 189
11.11.2013, 14:53     Класс со значением полей "по умолчанию" #25
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Конструктор копирования по-умолчанию
TStudent::TStudent (const TStudent& Student)
{
    //В конструкторе копирования, так же выделим память на которые указывают указатели
    LastName = new char[strlen(Student.LastName) + 1]; 
    FirstName = new char[strlen(Student.FirstName) + 1];
    Patronimyc = new char[strlen(Student.Patronimyc) + 1];
     Group = new char[strlen(Student.Group) + 1];
   
    //И скопируем в них значения из объекта класса на базе которого мы создаем объект путем копирования
   strcpy(LastName, Student.LastName);
   strcpy(FirstName, Student.FirstName);
   strcpy(Patronimyc, Student.Patronimyc);
   strcpy(Group, Student.Group);
   Born = Student.Born;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Перегрузка оператора присвоения 
TStudent TStudent::operator= (TStudent& Student) //Оператор присвоения
{
if (this == &Student) //проверка на самоприсваивание
return *this;
 
delete [] LastName;
delete [] FirstName;
delete [] Patronimyc;
delete [] Group;
 
     LastName = new char[strlen(Student.LastName) + 1]; 
    FirstName = new char[strlen(Student.FirstName) + 1];
    Patronimyc = new char[strlen(Student.Patronimyc) + 1];
     Group = new char[strlen(Student.Group) + 1];
strcpy(LastName, Student.LastName);
   strcpy(FirstName, Student.FirstName);
   strcpy(Patronimyc, Student.Patronimyc);
   strcpy(Group, Student.Group);
     Born = Student.Born;
    return *this;
}
Добавлено через 2 минуты
даже еще лучше возвращать объект в операции присваивания по ссылке, а не по значению, т.е.

C++
1
TStudent& TStudent::operator= (TStudent& Student) //Оператор присвоения
соответственно в классе тоже нужно изменить прототип это функции

Добавлено через 3 минуты
Цитата Сообщение от Tulosba Посмотреть сообщение
Неопределенности нет. В данном случае поля не будут проинициализированы вовсе.
Ну а в чем тогда польза такого конструктора, если поля не будут проинициализированы вовсе?

Добавлено через 1 минуту
Адренс Аксидор, еще лучше так будет написать
C++
1
TStudent& TStudent::operator= (const TStudent& Student) //Оператор присвоения
Добавлено через 2 минуты
Адренс Аксидор, будут ошибки еще выкладывайте)у меня IDE под рукой сейчас нет, поэтому пишу прямо здесь
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
11.11.2013, 14:57     Класс со значением полей "по умолчанию" #26
Цитата Сообщение от Extrim88 Посмотреть сообщение
Ну а в чем тогда польза такого конструктора, если поля не будут проинициализированы вовсе?
Пользы нет потому что писать так не следует. Это логическая ошибка. Для того чтобы избежать ошибки, можно параметры объявить константными. Тогда присвоить значение самому себе не получится.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.11.2013, 15:05     Класс со значением полей "по умолчанию"
Еще ссылки по теме:

Visual жалуется на конструктор "Error C2512: нет подходящего конструктора по умолчанию" - C++
Привет, мне Visual C++ выдал такие ошибки делаю все как в уроке, пытаюсь описать класс в заголовочном файле, вот код с...

Для класса "R" не существует конструктор по умолчанию - C++
Подскажите, что не так. И как здесь пользоваться cout? Чтобы вывести с. Просто я вбивал, а он не работает. И где его вообще вбивать нужно? ...

Исправить ошибку "выражение должно быть допустимым для изменения левосторонним значением" - C++
#include &lt;iostream&gt; const int N = 10; class mc { public: char s1, s2; void input(); //ввод void output(); //вывод ...

Выдает ошибки : "выражение должно быть допустимым для изменения левосторонним значением" - C++
В строке 75: fam3.surname_people= fam2.surname_people; выдает ошибки : &quot;выражение должно быть допустимым для изменения левосторонним...

Исправить ошибку "выражение должно быть допустимым для изменения левосторонним значением" - C++
проблема когда задаю функцию, пишет &quot; +6 перегрузок выражение должно быть допустимым для изменения левосторонним значением&quot; помогите...


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

Или воспользуйтесь поиском по форуму:
Адренс Аксидор
5 / 5 / 1
Регистрация: 16.05.2012
Сообщений: 92
11.11.2013, 15:05  [ТС]     Класс со значением полей "по умолчанию" #27
Спасибо, все заработало!
Yandex
Объявления
11.11.2013, 15:05     Класс со значением полей "по умолчанию"
Ответ Создать тему
Опции темы

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