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

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

Войти
Регистрация
Восстановить пароль
 
Fareiro
15 / 15 / 1
Регистрация: 06.12.2012
Сообщений: 132
#1

Конструктор класса - C++

18.03.2013, 02:17. Просмотров 536. Ответов 12
Метки нет (Все метки)

Добрый вечер. Поясните кто может)
Есть класс
C++
1
2
3
4
5
6
7
8
9
10
class Person
{
public:
    Person(void);
    ~Person(void);
    
    char Name[30];
    char Surname[30];
    char PESEL[11];
}
нужно сделать конструктор, с помощью которого во время создания объекта можно будет задать name, surname, pesel.

как это правильно сделать?

Добавлено через 1 минуту
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
/////main\\\\\
       
        char Name, Surname, PESEL;
    
    cout << "Enter name: ";
    cin >> Name;
    cout << "Enter surname: ";
    cin >> Surname;
    cout << "Enter PESEL: ";
    cin >> PESEL;
 
    Person* p;
    p = new Person(Name, Surname, PESEL);
.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Person::Person(char Name, char Surname, char PESEL)
{
    Person::set_name(Name);
    Person::set_surname(Surname);
    Person::set_pesel(PESEL);
}
void Person::set_name(char Name)
{
    Name = Name;
}
 
void Person::set_surname(char Surname)
{
    Surname = Surname;
}
void Person::set_pesel(char PESEL)
{
    PESEL = PESEL;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.03.2013, 02:17
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Конструктор класса (C++):

Конструктор класса не видит конструктор по умолчанию другого класса - C++
Ошибка, естественно, в Classes.cpp, в строке 20. Ругается, что у класса TailNode нет конструктора по умолчанию, хотя он там, конечно, есть....

Конструктор производного класса требует конструктор предка - C++
Выдаёт вот такую вот ошибку: no matching function for call to 'Cube::Cube()' class Cube { protected: int magInt; bool...

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

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

В конструктор класса передать объект этого класса - C++
Вопрос на засыпку :) Как в конструктор класса передать объект этого класса? Т.е. class A { public: A(const char* s){} ...

Конструктор класса с инициализацией другого класса - C++
error C2064: term does not evaluate to a function taking 6 arguments Так же при наведении на SStria(...); Пишет: call of an object of...

12
IrineK
Заблокирован
18.03.2013, 08:07 #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
#include <iostream>
#define buf 30
 
using namespace std;
 
class Person
{
public:
    Person (char*, char*, char*);
    ~Person(void);
 
    //setters
    void setName(char* N)       {strcpy(Name,N);}
    void setSurname(char* SN)   {strcpy(Surname,SN);}
    void setPESEL(char* PES)    {strcpy(PESEL,PES);}
 
    //getters
    char* getName()     {return Name;}
    char* getSurname()  {return Surname;}
    char* getPESEL()    {return PESEL;}
 
    //console dialogues
    void setConsolDialogue();
    void getConsolDialogue();
 
private:
    char Name[30];
    char Surname[30];
    char PESEL[30];
};
 
Person::Person(char* N, char* SN, char* PES)
{   setName(N);
    setSurname(SN);
    setPESEL(PES);
}
 
void Person::setConsolDialogue()
{   char *N = new char(buf);
    char *SN = new char(buf);
    char *PES = new char(buf);
    cout<<"Name:   \t";
    cin>>N;
    cout<<"Surname:\t";
    cin>>SN;
    cout<<"PESEL:  \t";
    cin>>PES;
    this->setName(N);
    this->setSurname(SN);
    this->setPESEL(PES);
}
 
void Person::getConsolDialogue()
{   cout<<"Name:   \t"<<Name<<"\n";
    cout<<"Surname:\t"<<Surname<<"\n";
    cout<<"PESEL:  \t"<<PESEL<<"\n";
}
 
 
int main()
{   Person *p = new Person("none","none","none");
    
    cout<<"Let me introduce myself :] \n";
    p->getConsolDialogue();
 
    cout<<"\nHelp me. I forgot everytihng about me :'(\n";
    p->setConsolDialogue();
 
    cout<<"\nThanks. Let me introduce myself again :-)\n";
    p->getConsolDialogue();
    
    cin.sync();cin.get();
    return 0;
}
0
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
18.03.2013, 09:45 #3
Похоже, что в данной задаче подразумевается работа с нуль-терминированными строками, АКА const 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
#include <cstring>
#include <iostream>
 
class Person {
 public:
  Person(const char *name, const char *surname, const char *pesel)
    : name(strcpy(new char[strlen(name) + 1], name)),
    surname(strcpy(new char[strlen(surname) + 1], surname)),
    pesel(strcpy(new char[strlen(pesel) + 1], pesel)) {}
  Person(const Person &other)
    : name(strcpy(new char[strlen(other.name) + 1], other.name)),
    surname(strcpy(new char[strlen(other.surname) + 1], other.surname)),
    pesel(strcpy(new char[strlen(other.pesel) + 1], other.pesel)) {}
  Person &operator=(const Person &other) {
    if (this != &other) {
      setName(other.getName());
      setSurname(other.getSurname());
      setPesel(other.getPesel());
    }
    return *this;
  }
  const char *getName() const { return name; }
  const char *getSurname() const { return surname; }
  const char *getPesel() const { return pesel; }
  void setName(const char *name) {
    delete [] this->name;
    this->name = strcpy(new char[strlen(name) + 1], name);
  }
  void setSurname(const char *surname) {
    delete [] this->surname;
    this->surname = strcpy(new char[strlen(surname) + 1], surname);
  }
  void setPesel(const char *pesel) {
    delete [] this->pesel;
    this->pesel = strcpy(new char[strlen(pesel) + 1], pesel);
  }
  virtual ~Person() {
    delete [] name;
    delete [] surname;
    delete [] pesel;
  }
 private:
  char *name;
  char *surname;
  char *pesel;
};
 
std::ostream &operator<<(std::ostream &stream, const Person &person) {
  return stream << "Person{" <<
    "name='" << person.getName() << "'," <<
    "surname='" << person.getSurname() << "'," <<
    "pesel='" << person.getPesel() << "'}";
}
 
int main(int argc,char **argv)
{
  Person person("Alexy", "Nowak", "76052209940");
  std::cout << person << std::endl;
 
  // change surname
  person.setSurname("Pawlak");
  std::cout << person << std::endl;
  return 0;
}
1
IrineK
Заблокирован
18.03.2013, 12:00 #4
После краткого ознакомления с Майерсом ) http://www.e-reading-lib.org/book.php?book=1002058
Добавляем const к указателям на строки, убираем мусор.
Не используем #define

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
#include <iostream>
using namespace std;
 
class Person
{
public:
    Person (const char*, const char*, const char*);
    ~Person(void);
 
    //setters
    void setName(const char* N)     {strcpy(Name,N);}
    void setSurname(const char* SN) {strcpy(Surname,SN);}
    void setPESEL(const char* PES)  {strcpy(PESEL,PES);}
 
    //getters
    const char* getName() const     {return Name;}
    const char* getSurname() const  {return Surname;}
    const char* getPESEL() const    {return PESEL;}
 
    //console dialogues
    void setConsolDialogue();
    void getConsolDialogue();
 
private:
    static const int buf = 30;
    char *Name;
    char *Surname;
    char *PESEL;
};
 
Person::Person(const char* N, const char* SN, const char* PES)
{   Name = new char[buf];
    Surname = new char[buf];
    PESEL = new char[buf];
    setName(N);
    setSurname(SN);
    setPESEL(PES);
}
 
Person::~Person()
{   delete []Name;
    delete []Surname;
    delete []PESEL;
}
 
void Person::setConsolDialogue()
{   char *N = new char[buf];
    char *SN = new char[buf];
    char *PES = new char[buf];
    cout<<"Name:   \t";
    cin>>N;
    cout<<"Surname:\t";
    cin>>SN;
    cout<<"PESEL:  \t";
    cin>>PES;
    this->setName(N);
    this->setSurname(SN);
    this->setPESEL(PES);
    delete []N;
    delete []SN;
    delete []PES;
}
 
void Person::getConsolDialogue()
{   cout<<"Name:   \t"<<Name<<"\n";
    cout<<"Surname:\t"<<Surname<<"\n";
    cout<<"PESEL:  \t"<<PESEL<<"\n";
}
 
int main()
{   Person *p = new Person("none","none","none");
    
    cout<<"Let me introduce myself :] \n";
    p->getConsolDialogue();
 
    cout<<"\nHelp me. I forgot everything about me :'(\n";
    p->setConsolDialogue();
 
    cout<<"\nThanks. Let me introduce myself again :-)\n";
    p->getConsolDialogue();
 
    p->Person::~Person();
 
    cin.sync();cin.get();
    return 0;
}
1
Fareiro
15 / 15 / 1
Регистрация: 06.12.2012
Сообщений: 132
18.03.2013, 13:41  [ТС] #5
Благодарю!
0
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
18.03.2013, 15:12 #6
Цитата Сообщение от IrineK Посмотреть сообщение
p->Person::~Person();
Это что за покемон?!
Это вместо delete p;? Ну тогда оно не освобождает память, выделенную под саму p.
В то время как delete p; заодно вызовет деструктор.

Цитата Сообщение от IrineK Посмотреть сообщение
static const int buf = 30;
Это вам зачем? Вы же можете при копировании вычислить, сколько памяти надо под хранение конкретной строки с помощью strlen и не использовать больше необходимого количества памяти, заодно и не бояться, что поле может оказаться более buf символов длиной.
0
IrineK
Заблокирован
18.03.2013, 16:11 #7
Покемон имеет право на жизнь: http://msdn.microsoft.com/en-us/library/35xa3368(v=vs.100).aspx
Why not?
0
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
18.03.2013, 16:50 #8
Цитата Сообщение от IrineK Посмотреть сообщение
Покемон имеет право на жизнь: http://msdn.microsoft.com/en-us/library/35xa3368(v=vs.100).aspx
Why not?
Не, я догадался, что это явный вызов деструктора. Но в данном контексте он бессмысленен и не заменяет освобождения памяти. delete p;
1
IrineK
Заблокирован
18.03.2013, 17:41 #9
Как раз память явный вызов деструктора освобождает - он ведь под это заточен в данном случае, поскольку удаляет три строки, составляющие объект.
Нужно еще занулить указатель на объект. Поэтому в строке 83 пишем
p = NULL;

Кстати, судя по коду, представленному здесь: http://msdn.microsoft.com/en-us/library/kewsb8ba(v=vs.100).aspx
указатель нужно занулять и при использовании delete. В указанном примере это выглядит так:
delete pName;
pName = NULL;

В Visual2010 есть проблемы с использованием delete в лоб в пользовательских классах, связанные с концепцией уборки мусора. А явный вызов деструктора действует всегда - это тоже аргумент в его пользу.
0
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
18.03.2013, 23:26 #10
Цитата Сообщение от IrineK Посмотреть сообщение
Как раз память явный вызов деструктора освобождает
Память, выделенную при помощи оператора new под сам объект (на который указывает this объекта) явный вызов деструктора не освобождает.

Цитата Сообщение от IrineK Посмотреть сообщение
указатель нужно занулять и при использовании delete.
Это не обязательно, но хорошая привычка. Указатель, указывающий на 0 можно смело delete, и это не вызовет исключений.

Цитата Сообщение от IrineK Посмотреть сообщение
В Visual2010 есть проблемы с использованием delete в лоб в пользовательских классах, связанные с концепцией уборки мусора. А явный вызов деструктора действует всегда - это тоже аргумент в его пользу.
Не понял. "Уборки мусора" в стандарте С++ нет.
1
Kuzia domovenok
1960 / 1813 / 142
Регистрация: 25.03.2012
Сообщений: 6,286
Записей в блоге: 1
18.03.2013, 23:48 #11
Цитата Сообщение от IrineK Посмотреть сообщение
Как раз память явный вызов деструктора освобождает
ты не прав. Спорить бессмысленно. Явный вызов деструктора нужен очень редко. Я слышал, его используют во всяких самодельных менеджерах памяти. Сам никогда не пользовался им.

Добавлено через 4 минуты
Цитата Сообщение от IrineK Посмотреть сообщение
указатель нужно занулять
ты не прав. Указатель это та же переменная, предназначенная для хранения адресов памяти. Если тыпосле вызова delete не запишешь в неё NULL, или даже наоборот, присвоишь ей значение абракадабры(p=0xABCD; ).Ничего не произойдёт. Вот если ты попытаешься разыменовать этот указатель и записать данные по "инвалидному" адресу - жди беды.
0
IrineK
Заблокирован
19.03.2013, 07:28 #12
Дискуссия о занулении указателей уже не раз возникала на форуме. Например, здесь: Указатели и сссылки. Надо ли обнулять? когда и как это делать?

При этом высказывания не столь категоричны, как у моих уважаемых оппонентов)
Нисколько не сомневаясь в их компетенции и их выборе, позволю себе описание процессов, происходящих при использовании delete, для более заинтересованной аудитории.

Немного "подрихтуем" последний вариант кода. Создадим функцию для непосредственного вывода объекта в потоке.
Для этого в объявлении класса среди уже имеющихся функций добавим:
C++
1
friend const ostream& operator<<(ostream& stream,const Person& obj);
и опишем ее ниже:
C++
1
2
3
4
5
const ostream& operator<<(ostream&stream,const Person& obj)
{
    stream<<obj.Name<<"\t"<<obj.Surname<<"\t"<<obj.PESEL<<"\n";
    return stream;
}
Теперь, после того, как поиграли с объектом класса, будем его удалять.
Добавим строки:
C++
1
2
3
cout<<"\nBefore delete: "<<&p<<"\t"<<p<<"\t"<<*p;
    delete p;
    cout<<"\nAfter delete: "<<&p<<"\t"<<p<<"\t"<<*p; //здесь попытка вывода *р приведет к крашу
Конечно же, мы вылетаем при попытке обращения к объекту (*р) после delete – взять нечего (память в куче освобождена), но указатель НЕ занулен (р = 0027f92c, он остался в стеке).
Адрес и значение указателя после delete мы по-прежнему получили (см.рис.1)

Объяснение: при удалении адресуемого указателем p объекта с самим указателем p, с его значением ничего не происходит. Оператор delete освобождает память в куче, указатель же p располагается в стеке, отведенная под него память будет освобождена только при выходе p из области видимости. После выполнения delete в ячейках памяти, занимаемых указателем p в стеке, будет записана та же информация — число 0027f92c — адрес уже несуществующего объекта.

Таким образом, после выполнения оператора delete мы получаем недействительный указатель (dangling pointer), указатель, который адресует несуществующий объект. Для обработки исключений вручную имеет смысл сразу после удаления объекта присвоить указателю на него значение NULL, тем самым явно идентифицировав этот указатель как ни на что не указывающий.

Попробуем так (конечно, уже без попыток добраться до *р после delete):
C++
1
2
3
4
5
cout<<"\nBefore delete: "<<&p<<"\t"<<p<<"\t"<<*p;
    delete p;
    cout<<"\nAfter delete: "<<&p<<"\t"<<p;
    p = NULL;
    cout<<"\nAfter delete and NULL: "<<&p<<"\t"<<p;
Результат - на рис.2. Указатель благополучно занулился. Можно обрабатывать, не допуская нежелательных процессов.

Возникает вопрос: почему компилятор автоматически не присваивает ссылке NULL при операции delete?
Причина - количество указателей, ссылающихся на данный объект, компилятору неизвестно. Можно занулить данный указатель, но как быть со всеми остальными? Поэтому - дело за вами, как говорит один из корифеев данного форума - "поработайте ручками" )
0
Миниатюры
Конструктор класса  
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
19.03.2013, 08:55 #13
Цитата Сообщение от IrineK Посмотреть сообщение
Возникает вопрос: почему компилятор автоматически не присваивает ссылке NULL при операции delete?
Лишняя операция. Пользователь, если будет надо, сам обнулит. Можно еще попробовать составить код так, чтобы исключить обращение к уже удаленным объектам. RAII знакомо?

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

Пример, вызывающий деструктор и обнуляющий адрес, вместо освобождения памяти.
Все очень быстро закончится bad_alloc'ом.
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
#include <iostream>
 
class Large {
 public:
  Large() {}
  virtual ~Large() {}
 private:
  char data[1048576];
};
 
int main(int argc,char **argv) {
  size_t counter = 0;
  while (true) {
    try {
      Large *object = new Large();
      object->Large::~Large();
      object = NULL;
      //delete object; // если память освобождать, выделять можно будет практически бесконечно долго.
    } catch (std::exception &e) {
      std::cout << "Error: " << e.what() << std::endl;
      break;
    }    
    std::cout << ++counter << " allocations made." << std::endl;
  }
  
  std::cin.get();
  return 0;
}
0
19.03.2013, 08:55
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.03.2013, 08:55
Привет! Вот еще темы с ответами:

Конструктор класса - C++
Для чего используется второй конструктор, если при объявлении полей класса и так указывается их тип? class fraction { ...

Конструктор класса - C++
Необходимо, чтобы при задании планеты (сферы) высчитывался гравитационный параметр, желательно в конструкторе. Данный код не компилируется,...

Конструктор класса - C++
Интересно, а может ли быть конструктор класса не публичнымм, а приватным?

Конструктор класса - C++
задание: Класс кольцо. В классе определить поля с координатами центра кольца, большим и малыми радиусами, автовычисляемые поля с площадью и...


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

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

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