C언어

c++ 공부 요점 정리 7

뮹실이 2013. 11. 20. 21:50







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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// =====================================================
// 22 객체의 소멸
// =====================================================
// 객체가 소멸되는 시점
// : 기본 자료형 변수, 구조체 변수가 소멸되는 시점과 동일
//
// 함수내에 선언된 객체
// : 함수 호출이 끝나면 소멸
//
// 전역적으로 선언된 객체
// : 프로그램이 종료될때 소멸
//   전역으로 객체를 선언할 일은 거의 없다
//   객체 지향에서는 전역이라는 개념은 없다
//   객체 지향에서는 전역을 대신하는
//   static 멤버 변수, static 멤버 함수가 존재
//
//
// 생성자와 동적할당
#include<iostream>
using std::cout;
using std::endl;

class Person
{
	char *name;
	char *phone;
	int age;
public:
	Person(char* _name, char* _phone, int _age);
	void ShowData();
};

Person::Person(char* _name, char* _phone, int _age)
{
	name=new char[strlen(_name)+1];
	// strlen : NULL문자를 제외한
	//          문자열의 길이를 리턴받는 함수
	//          3이 리턴되고 NULL을 포함한
	// 길이가 4인 char형 배열이 힙에 할당됨
	
	strcpy(name, _name);
	// 할당된 힙의 포인터가 name에 대입됨
	// name이라는 멤버는 동적할당된 힙을 
	// 가리키게 됨
	// p라는 객체는 main에서 선언이 되었으므로
	// 스택에 할당됨
	// p 객체(스택)는 문자열 저장공간을 위해
	// 할당된 힙의 메모리 공간을 가리킴

	phone=new char[strlen(_phone)+1];
	strcpy(phone, _phone);

	age=_age;
}

int main()
{
	Person p("abc", "333", 22);
	// 
	return 0;
}
// 동적할당을 통해 메모리 공간을 효줄적으로 사용
// 그러나 동적할당을 해주면 직접해제를 해줘야
// 하는 번거로움이 있다
// 객체가 사라진다고 해서 힙영역에 할당된
// 메모리가 사라지는게 아니라 직접 해제해야함
//
// 그럼 메모리를 해제하는 방법은?
// 메모리를 해제하는 멤버함수를 추가하는 방법
// 클래스 person에 다음 public 함수 추가하고
void Person::DelMemory()
{
	delete []name;
	delete []phone;
}
// 메인함수에서 다음을 호출하면 메모리해제 완료
// p 객체가 사라지기전(함수 호출이 끝나기전에)
// 에 메모리를 해제해야함
// 
p.DelMemory();

// 객체가 사라지기 전에 객체의 메모리할당 해제가
// 부담스럽다
// 따라서 다른 방법 사용
// 자동적으로 해제 되면 좋겠다
// 
// 생성자 : 객체의 멤버변수 초기화를 위해서
//          객체 생성시 자동 호출되는 함수
//
// 소멸자 : 객체의 메모리 반환을 위해서
//
//          ,즉 생성자에서 할당해논 메모리 공간을
//
//          객체 소멸시 자동 호출되는 함수
//
//          클래스의 이름앞에 ~가 붙은 형태
//
//          리턴하지 않으며, 리턴 타입도 없다
//
//          전달인자는 항상 void이다.
//
//          즉, 전달인자를 받을 수 없는 형태이다
//
//          전달인자를 받을 수 없다는 것은
//
//          오버로딩이 불가능하다는 것이고
//
//          (오버로딩은 전달인자의 갯수나 타입이 
//
//          달라야지만 가능하기때문)
//
//          전달인자가 없기 때문에 
//
//          디폴트 매개변수의 선언이 불가능하다
//
// 예제
//
// 객체의 소멸 순서
// 1. 소멸자 호출
// 2. 메모리 반환
//
// 소멸자를 먼저 호출해줌으로 인해서
// 메모리가 반환될때 반환되지 않은 
// 메모리 공간을 명시적으로 반환하기
// 위해서이다
//
#include<iostream>
using std::cout;
using std::endl;

class Person
{
	char *name;
	char *phone;
	int age;
public:
	Person(char* _name, char* _phone, int _age);
	~Person(); // 소멸자 선언
				// 반드시 전달인자 받지않는
				// void 형태이어야함
};

Person::Person(char* _name, char* _phone, int _age)
{
	name=new char[strlen(_name)+1];
	strcpy(name, _name);

	phone=new char[strlen(_phone)+1];
	strcpy(phone, _phone);

	age=_age;
}
Person::~Person()
{
	delete []name;
	delete []phone;
}


int main()
{
	Person p("KIM", "013-333-5555", 22);
	return 0;
}
// 이런식으로 구성하면 
// p.DelMemory(); 이런식으로 따로 호출해야하는
// 부담이 사라짐

//
// 예제 2
//
class AAA
{
public:
	AAA(){
		cout<<""생성자 호출"<<endl;
	}
	~AAA(){
		cout<<""소멸자 호출"<<endl;
	}
}

int main()
{
	AAA aaa1; // "생성자 호출" 메시지 출력
	AAA aaa2; // "생성자 호출" 메시지 출력
	return 0; // 리턴과 동시에 aaa1, aaa2 객체 소멸
}

// 디폴트 소멸자
//
// : 디폴트 생성자를 선언하지 않았다면
//
//   객체 생성의 순서를 지켜주기 위해서
//
//   형식적으로 제공되는 디폴트 생성자와
//
//   마찬가지로
//
//   디폴트 소멸자를 선언하지 않았다면
//
//   객체 소멸의 순서를 지켜주기 위해서
//
//   형식적으로 디폴트 소멸자를 제공한다
//
//   디폴트 소멸자는 하는일이 아무거도 없다
//
// 소멸자는 생성자에서 메모리 동적 할당을 
// 하는 경우에 필요하다
// 또는 디버깅 코드 작성시에 필요하다
// (객체 소멸 시점을 알수 있도록 cout 문을
//  넣어둔다든지 해서..)