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
// ##########################################
//
// 46 다중 상속에 대한 이해
//
// ##########################################
//
// 다중상속은 문법적 가치가 아주 낮아서 
// 사용을 권장하지 않는다.
// 
//
// 다중 상속의 예
//
#include <iostream>
using std::cout;
using std::endl;

class AAA{
public:
	void String1(){
		cout<<"AAA::String1"<<endl;
	}
};

class BBB{
public:
	void String2(){
		cout<<"BBB::String2"<<endl;
	}
};

class CCC : public AAA, public BBB{
public:
	void ShowString(){
		String1();
		String2();
	}
};

int main(void)
{
	CCC ccc;
	ccc.ShowString();

	return 0;
}

//
// 다중 상속의 모호성
//
#include <iostream>
using std::cout;
using std::endl;

class AAA{
public:
	void String(){
		cout<<"AAA::String"<<endl;
	}
};

class BBB{
public:
	void String(){
		cout<<"BBB::String"<<endl;
	}
};

class CCC : public AAA, public BBB{
public:
	void ShowString(){
		// 아래는 에러 발생
		String();  
		String();  
		// 다음과 같이 에러 해결
		// 그러나 이렇게 사용하는건
		// 코드가 지저분해지는 길..
		// 이래서 다중상속을 하면안된다..
		// AAA::String();
		// BBB::String();
	}
};

int main(void)
{
	CCC ccc;
	ccc.ShowString();

	return 0;
}

//
// virtual base 클래스 예제
//
// BBB, CCC 클래스가 AAA 클래스를 각각 상속하고 있는데
// DDD 클래스가 BBB 클래스와 CCC 클래스를 상속하게되어
// DDD 클래스의 객체 내에는 AAA 클래스를 상속하는
// BBB 클래스와 AAA 클래스를 상속하는 CCC 클래스를 
// 가지게 된다.
// 즉, AAA 클래스가 DDD 클래스속에 중복으로 존재하게 된다.
//
//
#include <iostream>
using std::cout;
using std::endl;

class AAA{
public:
	void String1(){
		cout<<"AAA::String"<<endl;
	}
};

class BBB : public AAA{   // class BBB : virtual public AAA
public:
	void String2(){
		cout<<"BBB::String"<<endl;
	}
};

class CCC : public AAA{  // class CCC : virtual public AAA
public:
	void String3(){
		cout<<"CCC::String"<<endl;
	}
};

class DDD : public BBB, public CCC {
public:
	void ShowString(){
		String1();// error
		// 이런식으로 사용해야한다.
		// AAA 클래스가 두번 상속되었기 때문에
		// 어디 클래스의 string1을 호출할지 
		// 결정해줘야 한다.
		// 
		// BBB::String1();
		// CCC::String1();
		
		String2();
		String3();
	}
};


int main(void)
{
	DDD ddd;
	ddd.ShowString();

	return 0;
}

// 이러한 문제를 해결하기 위해서
// 추가된 개념이 있다.
// BBB 클래스가 AAA 클래스를 가상으로 상속하고
// CCC 클래스가 AAA 클래스를 가상으로 상속할 때
// BBB 클래스와 CCC 클래스를 동시에 상속하는 
// 클래스 내에서는 AAA 클래스를 한번만 선언한다.
// 상속 선언시 virtual 을 선언해주면된다.
//
//
#include <iostream>
using std::cout;
using std::endl;

class AAA{
public:
	void String1(){
		cout<<"AAA::String"<<endl;
	}
};

class BBB : virtual public AAA{   // class BBB : virtual public AAA
public:
	void String2(){
		cout<<"BBB::String"<<endl;
	}
};

class CCC : virtual public AAA{  // class CCC : virtual public AAA
public:
	void String3(){
		cout<<"CCC::String"<<endl;
	}
};

class DDD : public BBB, public CCC {
public:
	void ShowString(){
		// error가 발생하지 않는다.
		// AAA 클래스가 하나만 상속되기 때문에
		String1();
		
		String2();
		String3();
	}
};


int main(void)
{
	DDD ddd;
	ddd.ShowString();

	return 0;
}

//
// 이러한 다중 상속들은 사용하지 말아야한다.!!!!
//








Posted by 뮹실이






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
// ##########################################
//
// 45 가상함수가 동작하는 원리
//
// ##########################################
//
//
// 다음과 같이 fct1, fct2, fct3는 모두 코드영역의
// 메모리 공간으로 올라가는데
// 클래스에 멤버함수중에서 하나라도 virtual로 선언되면
// 그 클래스의 멤버함수 정보를 지니는 버추얼테이블이 
// 형성된다.
// 모슨 A 클래스의 객체는 함수를 호출할 때 마다
// 버추얼테이블을 참조하게 된다.
// 이 버추얼테이블은 A 클래스의 fct1 함수가 어디에 있는지의
// 정보를 가지고 있고
// A 클래스의 fct2 함수가 어디에 있는지의 정보를 
// 가지고 있다.
// 즉 모든 멤버함수의 정보를 가지고 있다. 
// A 클래스의 aaa 객체의 fct1 함수를 호출하면
// 무조건 버추얼 테이블의 키값을 참조하게된다.
// fct1 함수의 key값을 찾고 value에 있는 위치찾아가 
// fct1 함수를 호출하게 된다.
// 즉, 가상함수를 선언함으로 인해서 버추얼테이블에 의한
// 메모리 소모와 버추얼 테이블을 참조함으로 인한 
// 함수 호출단계가 추가되어 함수 호출이 늦어지는 
// 단점이 있다.
// 
// B 클래스의 경우 A 클래스를 상속하기 때문에
// A 클래스의 멤버 함수도 멤버로 가지게 된다.
// 따라서 A클래스의 fct1, fct2, B 클래스의 fct1, fct3함수
// 의 정보를 버추얼테이블에서 가지고 있어야한다.
// 그러나 B클래스의 fct1에 의해서 오버라이딩된
// A 클래스의 fct1함수는 B 클래스의 버추얼테이블에
// 정보를 가지고 있지 않는다.
// 그래서 A 클래스의 포인터로 fct1 함수를 호출하던
// B 클래스의 포인터로 fct1 함수를 호출하던
// B 클래스의 fct1 함수만이 호출되는 것이다.
//
#include <iostream>
using std::endl;
using std::cout;

class A
{
	int a;
	int b;
public:
	virtual void fct1(){
		cout<<"fct1(...)"<<endl;
	}
	virtual void fct2(){
		cout<<"fct2(...)"<<endl;
	}	
};

class B : public A
{
	int c;
	int d;
public:
	virtual void fct1(){
		cout<<"overriding fct1(...)"<<endl;
	}
	void fct3(){
		cout<<"fct3(...)"<<endl;
	}
};

int main(void)
{
	A* aaa=new A();
	aaa->fct1();

	B* bbb=new B();
	bbb->fct1();
	
	return 0;
}

//
// 이러한 가상함수의 단점에도 불구하고
// 가상함수의 장점이 훨씬 크기 때문에
// 가상함수를 많이 사용한다.
//





Posted by 뮹실이






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
// ##########################################
//
// 44 멤버 함수의 위치
//
// ##########################################
//
// 객체에 의해서 공유되는 멤버 함수
//
// 
class AAA
{
	int n;
	
	public :
		A(int n){
			this->n = n;
		}
		
		void add(){
			n++;
		}
}

void main()
{
	// AAA 객체를 생성 할 때마다 add 함수가 
	// 각 객체 내에 중복으로 존재하면
	// 비효율적이다.
	// 실제는 각 객체들은 하나의 add 함수를 공유한다.
	// 일단, 컴파일하면
	// 코드자체가 코드영역이라 불리는 메모리 영역에 
	// 올라간다.
	// AAA 클래스의 add 함수 또한 코드 영역의 메모리
	// 공간에 올라간다.
	// a1 객체의 add 함수를 호출하면 코드 영역의 메모리
	// 공간에 올라간 add 함수를 호출하고
	// a2 객체의 add 함수를 호출하면 코드 영역의 메모리
	// 공간에 올라간 add 함수를 호출한다.
	// 즉 각 객체의 멤버함수는 코드영역의 함수를 공유한다.
	// 그러면 코드영역의 add 함수는 어떻게
	// a1에서 add 함수를 호출하면 a1의 멤버변수를 조작하고
	// a2에서 add 함수를 호출하면 a2의 멤버변수를 조작하느냐면
	// add 함수가 코드 영역에 올라갈때 
	// AAA 클래스의 포인터를 인자로 받도록 변경되어 
	// 올라간다.
	// void add(AAA* a)
	// { (a->n)++;}
	// 이런식으로 객체의 포인터를 전달 인자로 전달하기
	// 때문에 함수의 공유가 가능하다.
	//
	AAA a1(10);
	AAA a2(20);
	
	a1.add();
	a2.add();
}








Posted by 뮹실이

2013. 12. 5. 22:11 C언어

c++ 공부 요점정리 26







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
// ##########################################
//
// 43 Virtual 소멸자의 필요성
//
// ##########################################

#include <iostream>
using std::endl;
using std::cout;

class AAA
{
	char* str1;
public:
	AAA(char* _str1){
		// 생성자 내에서 동적할당하므로
		str1= new char[strlen(_str1)+1];
		strcpy(str1, _str1);
	}
	~AAA(){			// virtual ~AAA()
		cout<<"~AAA() call!"<<endl;
		// 소멸자에서 메모리 해제한다.
		delete []str1;
	}
	virtual void ShowString(){
		cout<<str1<<' ';
	}
};

// bbb 클래스가 소멸될 때는 bbb 클래스의 소멸자도
// 호출되지만
// 상속하고 있는 aaa 클래스의 소멸자도 호출된다.
// bbb 클래스 객체가 생성될때
// bbb 클래스의 생성자에 의해서 동적할당하고
// aaa 클래스의 생성자에 의해서 동적할당하고
// 두군데에서 할당된 메모리공간이 
// 각각의 소멸자에 의해서 적절히 해제된다.
//
class BBB : public AAA
{
	char* str2;
public:
	BBB(char* _str1, char* _str2) : AAA(_str1){
		// 생성자 내에서 동적할당하므로
		str2= new char[strlen(_str2)+1];
		strcpy(str2, _str2);
	}
	~BBB(){
		cout<<"~BBB() call!"<<endl;
		// 소멸자에서 메모리 해제한다.
		delete []str2;
	}
	virtual void ShowString(){
		AAA::ShowString();
		cout<<str2<<endl;
	}
};

/***** main function **************/
int main()
{
	// bbb 클래스 객체를 생성하면
	// aaa 클래스의 생성자도 호출된다.
	BBB * b=new BBB("Good", "morning");
	b->ShowString();
	delete b;
	// bbb 클래스의 객체가 소멸될때는
	// 상속하는 aaa 클래스의 소멸자도 호출된다.
	
	// bbb 클래스의 객체를 생성하면
	// aaa 클래스의 생성자도 호출되지만
	AAA * a=new BBB("Good", "evening");
	a->ShowString();	
	delete a;
	// aaa 클래스의 객체가 소멸될때는
	// bbb 클래스의 소멸자가 호출되지 않아
	// 메모리 유출이 발생한다.
	// bbb 클래스의 객체를 생성했지만
	// 소멸의 주체가 aaa 클래스이기 때문에
	// aaa 클래스의 소멸자만 호출하기 때문에
	// 문제 발생
	// 이문제를 해결하기 위해서는
	// aaa 클래스의 소멸자를 가상함수로 선언하면된다.
	// aaa 클래스의 소멸자를 가상함수로 선언하면
	// aaa 클래스의 소멸자를 호출할때 가상함수이므로
	// bbb 클래스의 소멸자가 대신 호출된다.
	// 소멸자를 오버라이딩할순없지만 소멸자의 경우는
	// 오버라이딩이 소멸자끼리 된다.
	// 따라서 bbb 클래스의 소멸자가 호출되고
	// bbb 클래스가 상속하고 있는
	// 다시 aaa 클래스의 소멸자가 호출되어 완전히
	// 메모리 해제가 된다.
		
	return 0;
}









Posted by 뮹실이

2013. 12. 5. 22:10 C언어

c++ 공부 요점정리 25






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
// ##########################################
//
// 42 Virtual의 특성도 상속된다
//
// ##########################################
// 멤버 함수를 가상(virtual)으로 선언하기
// : virtual 특성도 상속된다.
//
//
//
#include <iostream>
using std::endl;
using std::cout;

class AAA
{
public:
	virtual void fct(){
		cout<<"AAA"<<endl;
	}
};

class BBB : public AAA
{
public:
	// aaa 클래스의 가상함수 fct함수가 
	// bbb 클래스의 fct 함수에 의해서
	// 오버라이딩 되고 있다.
	// bbb 클래스가 상속하고있는 
	// aaa 클래스의 가상 fct 함수를
	// 오버라이딩을 하는 경우
	// 오버라이딩하는 bbb 클래스의 fct 함수도 자동으로
	// 가상함수로 선언되게 된다.
	// 따라서 명시적으로 가상을 선언하거나
	// 선언하지 않아도 같다.
	// 그러나 가독성을 위해서 가상을 선언해주는것이 좋다.
	// 
	void fct(){    // virtual void fct()
		cout<<"BBB"<<endl;
	}
};

class CCC : public BBB
{
public:
	// 마찬가지로 다음의 fct 함수도 가상함수가 된다.
	// ccc 클래스의 fct 함수는 가상함수가 되지만
	// 가상함수는 상속관계에 의해서 오버라이딩 되어
	// 질때만 의미를 가지기 때문에
	// 의미가 없는 가상함수가 된다.	
	void fct(){
		cout<<"CCC"<<endl;
	}
};


int main(void)
{
	// ccc 클래스의 객체를 생성하는데
	// bbb 클래스의 포인터로 ccc 클래스 객체를 가리킨다.
	// bbb 클래스의 포인터로 fct함수를 호출하니까
	// bbb 클래스의 fct를 호출하려고 보니
	// 가상함수이므로 이 함수를 오버라이딩하는 
	// 함수가 대신 호출되어 
	// ccc 클래스의 fct 함수가 호출된다.
	
	BBB* b=new CCC;
	b->fct();

	// aaa 클래스의 포인터도 ccc 클래스의 객체를 가리킨다.
	// aaa 클래스의 포인터로 fct 함수를 호출하니까
	// aaa 클래스의 fct 함수를 호출하는데
	// 가상함수이므로 aaa 클래스의 가상 fct 함수를 
	// 오버라이딩하고 있는 bbb 클래스의 가상 fct 함수를
	// 호출하고 
	// bbb 클래스의 fct 함수도 가상이므로
	// bbb 클래스의 fct 함수를 오버라이딩 하고있는
	// ccc 클래스의 fct 함수를 호출한다.
	
	AAA* a=b;
	a->fct();

	delete b;
	return 0;
}
//
// 만약 위의 예제에서 bbb 클래스도 없고, 
// ccc 클래스도 없다면 
// aaa 클래스의 가상함수 선언은 의미가 없다.
// aaa 클래스의 가상함수 fct를 호출하면 
// 그냥 호출된다.
// 따라서 가상함수는 가상함수고 속하는 클래스가 
// 상속되고, 
// 상속하는 클래스의 멤버 함수에 의해서
// 오버라이딩 되는 경우에 의미를 가진다.


//
// static binding vs dynamic binding
//
// 다음과 같이 선언 후 fct 함수를 호출하면
AAA* a = new ???
a->fct();
// 어디에 존재하는 fct 함수가 호출 될까?
// ???에 따라서 호출되는 fct 함수가 달라진다.
// 즉, 포인터에 따라서 호출되는 함수가 결정되는
// 것이 아니라
// 그 포인터가 가리키는 객체에 따라서 
// 호출되는 함수가 결정되는것이다.
// 이것을 다이나믹 바인딩이라 한다.
// 
// 다음과 같이 선언하면
AAA a;
a.fct();
// 항상 aaa 클래스의 fct 함수만 호출된다.
// 이것을 스태틱 바인딩이라 한다.

//
// 오버라이딩 된 함수의 호출이 필요한 이유
//
#include <iostream>
using std::endl;
using std::cout;

class AAA
{
public:
	virtual void fct(){
		cout<<"AAA"<<endl;
	}
};

class BBB : public AAA
{
public:
	void fct(){
		// 오버라이딩된 aaa 클래스의 fct 함수를
		// 호출하는 방법 1
		AAA::fct();  
		cout<<"BBB"<<endl;
	}
};


int main(void)
{
	AAA* a=new BBB;
	cout<<"첫 번째 시도"<<endl;
	a->fct();  

	cout<<"두 번째 시도"<<endl;
	// 방법 2
	// 다음과 같이 범위를 지정해 주면
	// aaa 클래스의 fct 함수를 호출할 수 있다.
	// 이런 방법은 권장되지 않음
	// 첫번째 방법 사용 권장
	a->AAA::fct(); 

	return 0;
}

//
// 순수(pure) 가상함수와 추상 클래스
// 
// 추상 클래스는 하나이상의 순수 가상함수를
// 지니는 클래스로
// 추상 클래스는 완전한 클래스가 아니므로
// 객체화 될 수 없다.
// 객체화는 불가능하지만 포인터 선언까지 
// 불가능한것은 아니다.
//
class AAA
{
	private :
		int a;
	public :
		// 함수를 선언만 하지 정의를 하지 않는다
		virtual int fct()=0; // 순수 가상 함수
}









'C언어' 카테고리의 다른 글

c++ 공부 요점정리 27 멤버 함수의 위치  (0) 2013.12.09
c++ 공부 요점정리 26  (0) 2013.12.05
c++ 공부 요점정리 24  (0) 2013.12.04
c++ 공부 요점정리 23  (0) 2013.12.04
c++ 공부 요점정리 22  (0) 2013.12.04
Posted by 뮹실이

2013. 12. 4. 00:28 C언어

c++ 공부 요점정리 24







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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
// ##########################################
//
// 41 상속된 객체와 참조 관계
//
// ##########################################
//
// 객체 레퍼런스
// : 객체를 참조할 수 있는 객체 레퍼런스는
//   클래스 포인터의 특성과 같다.
//
// 클래스 객체의 포인터는 클래스의 객체 뿐만아니라
// 클래스를 상속하고 있는 클래스의 객체도 가리킬있다.
// 
// 다음과 같이 상속관계에 있으면
// 사람 클래스의 포인터를 이용해
// 사람, 학생, 파트타임 객체를 가리킬 수 있다.
// 마찬가지로
// 사람 클래스의 참조도
// 사람, 학생, 파트타임 객체를 가리킬 수 있다.
// 또한 학생 클래스의 참조는
// 학생, 파트타임 객체를 가리킬 수 있다.
// 
#include <iostream>
using std::endl;
using std::cout;

class Person
{
public:
	void Sleep(){ 
		cout<<"Sleep"<<endl;
	}
};

class Student : public Person
{
public:
	void Study(){
		cout<<"Study"<<endl;
	}
};

class PartTimeStd : public Student
{
public:
	void Work(){
		cout<<"Work"<<endl;
	}
};

int main(void)
{
	// 파트타임 클래스는 학생, 사람 클래스를
	// 상속하고 있기 때문에
	PartTimeStd p;
	
	// 학생 클래스의 레퍼런스를 이용해 
	// 파트타임 클래스의 객체를 참조한다.
	Student& ref1=p;
	
	// 사람 클래스의 레퍼런스를 이용해 
	// 파트타임 클래스의 객체를 참조한다.
	Person& ref2=p;
	
	p.Sleep();
	ref1.Sleep();
	ref2.Sleep();

	return 0;
}


// 객체 레퍼런스의 권한
// : 객체를 참조하는 레퍼런스의 권한은
//   클래스 포인터의 권한과 일치
//
//
//
#include <iostream>
using std::endl;
using std::cout;

class Person
{
public:
	void Sleep(){ 
		cout<<"Sleep"<<endl;
	}
};

class Student : public Person
{
public:
	void Study(){
		cout<<"Study"<<endl;
	}
};

class PartTimeStd : public Student
{
public:
	void Work(){
		cout<<"Work"<<endl;
	}
};

int main(void)
{
	PartTimeStd p;
	p.Sleep();
	p.Study();
	p.Work();

	// 사람 클래스의 참조는
	// 학생, 파트타임 객체를 참조할 수 있지만
	// 접근할 수 있는 영역은 사람 클래스의 
	// 내에 선언되어 있거나 사람 클래스가 상속
	// 하고있는 멤버로 제한된다.
	Person& ref=p;
	ref.Sleep();
//	ref.Study(); // Error의 원인
//	ref.Work();  // Error의 원인

	return 0;
}

//
// 오버라이딩(overriding)의 이해
// : 오버라이딩과 오버로딩을 혼돈하지 않도록 주의
// : base 클래스에 선언된 멤버와 같은 형태의
//   멤버를 derived 클래스에서 선언하는것
//   base 클래스의 멤버를 가리는 효과를 가짐
//   보는 시야(pointer)에 따라서 달라지는
//   효과를 가짐
//
#include <iostream>
using std::endl;
using std::cout;

class AAA
{
public:
	void fct(){
		cout<<"AAA"<<endl;
	}
};

class BBB : public AAA
{
public: 
	//AAA 클래스의 fct() 함수를 오버라이딩.
	// aaa 클래스의 fct 함수는
	// bbb 클래스의 fct 함수에 의해서
	// 오버라이딩 되었다.
	void fct(){ 
		cout<<"BBB"<<endl;
	}
};

int main(void)
{
	// b 객체를 생성하면
	// b 객체에는 bbb 클래스의 fct 함수가 있고
	// aaa 클래스의 fct 함수도 있다.
	// 그리고 aaa 클래스의 fct 함수는
	// bbb 클래스의 fct 함수에 의해
	// 오버라이딩 되어있는 상태이다.
	// 즉, 가려진 상태이다.(은닉되어졌다.)
	BBB b;
	
	// 그래서 b 객체의 fct 함수를 호출하면
	// 다음과 같이 호출하면
	// bbb 클래스의 fct 함수가 호출된다.
	// 은닉된 멤버는 보는 시야를 달리하면
	// 볼수도 있다. 다음 예제 참조
	b.fct();

	return 0;
}

//
//
//
#include <iostream>
using std::endl;
using std::cout;

class AAA
{
public:
	void fct(){
		cout<<"AAA"<<endl;
	}
};

class BBB : public AAA
{
public:
	void fct(){
		cout<<"BBB"<<endl;
	}
};

int main(void)
{
	// bbb 클래스의 포인터로 객체 b를 가리키고있다.
	BBB* b=new BBB;
	
	// 포인터가 "보는 시야"에 해당한다.
	// b 객체를 bbb 클래스의 포인터로 가리키면
	// bbb 클래스로 바라보는 것
	// 그렇기 때문에 bbb 클래스의 fct 함수가
	// 호출되고 bbb 클래스의 객체내의 모든
	// 멤버에 접근가능
	b->fct();

	// aaa 클래스의 포인터로 객체 b를 가리키고있다.
	AAA* a=b;
	
	// bbb 클래스의 객체이지만
	// aaa 클래스의 포인터로 가리키면
	// aaa 클래스의 객체로 바라보는 것이기 때문에
	// aaa 클래스의 멤버에만 접근가능하므로
	// aaa 클래스의 fct 함수가 보이게 되어
	// 가려졌던 aaa 클래스의 fct 함수
	// 호출이 가능해진다.
	a->fct();

	delete b;
	return 0;
}

//
// 멤버 함수를 가상(virtual)으로 선언하기
// : 오버라이딩 되는 경우의 특징
//
//
#include <iostream>
using std::endl;
using std::cout;

class AAA
{
public:
	// virtual 키워드가 추가됨
	// 즉, fct 함수를 가상으로 선언하겠다는 의미
	// 없는 함수로 인식하라 라는 의미
	virtual void fct(){
		cout<<"AAA"<<endl;
	}
};

class BBB : public AAA
{
public:
	void fct(){
		cout<<"BBB"<<endl;
	}
};

int main(void)
{
	// bbb 클래스의 포인터로 객체 b를 가리키고있다.
	BBB* b=new BBB;
	b->fct();

	// aaa 클래스의 포인터로 객체 b를 가리키고있다.
	AAA* a=b;
	
	// aaa 클래스의 포인터로 객체 b를 가리키면
	// 가려졌던 aaa 클래스의 fct 함수가 보이게 되어
	// aaa 클래스의 포인터로 fct 함수를 호출하면
	// aaa 클래스의 fct 함수가 호출되어야하지만
	// aaa 클래스의 fct 함수가 가상함수이므로
	// aaa 클래스의 fct 함수를 오버라이딩 하고있는
	// bbb 클래스의 fct 함수가 대신 호출된다.
	// 이 특성을 재정의 라고 한다.
	// 오버라이딩에서 버추얼 키워드를 사용하지 않으면
	// 은닉의 특성을 지니게 되고 
	// 버추얼 키워드를 사용하면 재정의의 특성을 지니게 된다.
	//
	a->fct();

	delete b;
	return 0;
}

//
// 멤버 함수를 가상(virtual)으로 선언하기
// : virtual 특성도 상속된다.
//
//










'C언어' 카테고리의 다른 글

c++ 공부 요점정리 26  (0) 2013.12.05
c++ 공부 요점정리 25  (0) 2013.12.05
c++ 공부 요점정리 23  (0) 2013.12.04
c++ 공부 요점정리 22  (0) 2013.12.04
c++ 공부 요점정리 21  (0) 2013.11.28
Posted by 뮹실이

2013. 12. 4. 00:27 C언어

c++ 공부 요점정리 23







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
// ##########################################
//
// 40 Employee Problem 해결
//
// ##########################################
#include <iostream>
using std::endl;
using std::cout;

class Employee
{
protected:
	char name[20];
public:
	Employee(char* _name){
		strcpy(name, _name);
	}	
	const char* GetName();
};
const char* Employee::GetName()
{
	return name;
}	

class Permanent : public Employee
{
private:
	int salary;  // 기본급여
public:
	Permanent(char* _name, int sal);
	int GetPay();
};

Permanent::Permanent(char* _name, int sal)
: Employee(_name)
{
	salary=sal;
}

int Permanent::GetPay()
{
	return salary;
}

class Department
{
private:
	Employee* empList[10];
	int index;
public:
	Department(): index(0) { };
	void AddEmployee(Employee* emp);
	void ShowList(); // 급여 리스트 출력.
};

void Department::AddEmployee(Employee* emp)
{
	empList[index++]=emp;
}
void Department::ShowList() // 급여 리스트 출력.
{
	for(int i=0; i<index; i++)
	{
		cout<<"name: "<<empList[i]->GetName()<<endl;
		//cout<<"salary: "<<empList[i]->GetPay()<<endl;
		cout<<endl;
	}
}

int main()
{
	//직원을 관리하는 CONTROL 클래스
	Department department;

	//직원 등록.
	department.AddEmployee(new Permanent("KIM", 1000));
	department.AddEmployee(new Permanent("LEE", 1500));
	department.AddEmployee(new Permanent("JUN", 2000));

	//최종적으로 이번달에 지불해야할 급여는?
	department.ShowList();	
	return 0;
}








'C언어' 카테고리의 다른 글

c++ 공부 요점정리 25  (0) 2013.12.05
c++ 공부 요점정리 24  (0) 2013.12.04
c++ 공부 요점정리 22  (0) 2013.12.04
c++ 공부 요점정리 21  (0) 2013.11.28
c++ 공부 요점정리 20  (0) 2013.11.27
Posted by 뮹실이

2013. 12. 4. 00:26 C언어

c++ 공부 요점정리 22






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
// ##########################################
//
// 39 상속된 객체와 포인터 관계
//
// ##########################################
//
// 객체 포인터 (객체를 가리킬수 있는 포인터)
// : 객체의 주소값을 저장할 수 있는 포인터
//   aaa 클래스의 포인터는 aaa 객체 뿐만아니라
//   aaa 클래스를 상속하는 derived 클래스 객체의
//   주소값도 저장 가능
//
// 사람 객체 포인터는 사람 객체를 가리킬수 있고
//                    학생 객체를 가리킬수 있고
//                    파트타임학생 객체를 가리킬수있다.
// 학생 객체는 학생 객체이자 사람 객체이기 때문이고
// 파트타임학생 객체는 파트타임학생 객체이자 
//                     학생 객체이자
//                     사람 객체이기 때문
// 즉, 사람 is a 사람
//     학생 is a 사람
//     파트타임학생 is a 사람
//
// 학생 객체 포인터는 사람 객체를 가리킬수 없고
//                    학생 객체를 가리킬수 있고
//                    파트타임학생 객체를 가리킬수있다.
// 사람 객체는 학생 객체가 될수 없고
// 파트타임학생 객체는 파트타임학생 객체이자 학생 객체이기 때문
//
// 즉, 학생 is a 학생
//     파트타임학생 is a 학생
//
//
//
// 예제
//
#include <iostream>
using std::endl;
using std::cout;

class Person
{
public:
	void Sleep(){ 
		cout<<"Sleep"<<endl;
	}
};

class Student : public Person
{
public:
	void Study(){
		cout<<"Study"<<endl;
	}
};

class PartTimeStd : public Student
{
public:
	void Work(){
		cout<<"Work"<<endl;
	}
};

int main(void)
{
	Person* p1=new Person;
	Person* p2=new Student;
	Person* p3=new PartTimeStd;

	p1->Sleep();
	p2->Sleep();
	p3->Sleep();

	return 0;
}

// 객체 포인터의 권한
// : 포인터를 통해서 접근할 수 있는 객체 멤버의 영역
//   aaa 클래스의 객체 포인터는 가리키는 대상에 상관없이
//   aaa 클래스 내에 선언된 멤버에만 접근 가능
//
//
//
#include <iostream>
using std::endl;
using std::cout;

class Person
{
public:
	void Sleep(){ 
		cout<<"Sleep"<<endl;
	}
};

class Student : public Person
{
public:
	void Study(){
		cout<<"Study"<<endl;
	}
};

class PartTimeStd : public Student
{
public:
	void Work(){
		cout<<"Work"<<endl;
	}
};

int main(void)
{
	// 파트타임 객체를 생성하면 이 객체안에는
	// 사람 클래스에 선언된 함수도 있고
	// 학생 클래스에 선언된 함수도 있고
	// 파트타임 클래스에 선언된 함수도 있다.
	// 파트타임 클래스의 객체는
	// 학생 클래스의 객체이자
	// 사람 클래스의 객체이므로
	// 사람 클래스의 포인터로 파트타임 객체를 
	// 가리킬수 있고
	// 학생 클래스의 포인터로 파트타임 객체를
	// 가리킬수 있고
	// 파트타임 클래스의 포인터로 파트탐임 객체를
	// 가리킬수 있다.
	// 비록 사람 객체 포인터, 학생 객체 포인터,
	// 파트타임 객체 포인터가 가리키는 대상은 같을지라도
	// 호출할 수 잇는 함수는 제한적이다.
	// 사람 객체 포인터로 가리킬수 있는 함수는 
	// 파트타임 객체 내의 사람 클래스의 함수이고
	// 학생 객체 포인터로 가리킬수 있는 함수는
	// 파트타임 객체 내의 학생 클래스의 함수와 
	// 사람 클래스의 함수이고
	// 파트타임 객체 포인터로 가리킬수 있는 함수는
	// 파트타임 객체 내의 모든 함수를 호출 할 수 있다.
	// 즉, 사람, 학생, 파트타임 클래스의 함수를 모두
	// 호출 할 수 있다.
	
	Person* p3=new PartTimeStd;

	p3->Sleep();
	
	// 
//	p3->Study(); // Error의 원인
//	p3->Work();  // Error의 원인

	return 0;
}

//
// 예제
//
#include <iostream>
using std::endl;
using std::cout;

class AAA
{
public:
	void a(){ 
		cout<<"a"<<endl;
	}
};

class BBB : public AAA
{
public:
	void b(){
		cout<<"b"<<endl;
	}
};

class CCC : public BBB
{
public:
	void c(){
		cout<<"c"<<endl;
	}
};

int main(void)
{
	CCC* c = new C();
	c->a();
	c->b();
	c->c();
	// ccc 클래스는 ccc 클래스이자
	// bbb 클래스이자
	// aaa 클래스이므로 
	// 다음 문장이 성립한다.
	BBB* b = c;
	AAA* a = b;
	//
	// a,b,c는 모두 같은 위치를 가리키지만
	// 
	b->a();
	b->b();
	
	a->a();
	// 호출할 수 있는 함수는 제한된다.
	
	return 0;
}








'C언어' 카테고리의 다른 글

c++ 공부 요점정리 24  (0) 2013.12.04
c++ 공부 요점정리 23  (0) 2013.12.04
c++ 공부 요점정리 21  (0) 2013.11.28
c++ 공부 요점정리 20  (0) 2013.11.27
c++ 공부 요점정리 19  (0) 2013.11.27
Posted by 뮹실이

2013. 11. 28. 22:57 C언어

c++ 공부 요점정리 21






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
// ##########################################
//
// 			36 상속을 하는 이유
//
// ##########################################
// 다른 두 클래스의 멤버가 같을때
// 반복적으로 같은 내용이 중복될때 사용

// ##########################################
//
// 				37 상속의 조건
//
// ##########################################
// 학생 클래스는 사람 클래스이다.
// 와 같은 is a 관계가 성립되어야한다.
// 사람클래스는 학생클래스이다.는 적절하지 않은
// 상속이다..
//
// derived 클래스가 base 클래스를 상속하면
// derived 클래스가 base 클래스의 특성을 
// 포함하기때문...

// ##########################################
//
// 				38 상속의 조건
//
// ##########################################
// has a (소유)관계에 의한 상속
//
// 학생 클래스는 책 클래스를 상속한다.
// 학생은 책을 소유한다.는 의미
//
// has a 관계에 의한 상속의 대안
// : 포함관계를 통해서 소유 관계를 표현
//   객체 멤버에 의한 포함관계 형성 (예제 1)
//   객체 포인터 멤버에 의한 
//   포함 관계의 형성 (예제 2)
//
//
// 예제 1
//
#include <iostream>
using std::endl;
using std::cout;

class Cudgel  //몽둥이
{ 
public:
	void Swing(){ cout<<"Swing a cudgel!"<<endl; }
};


class Police //몽둥이를 소유하는 경찰
{
	Cudgel cud;
	// 위 문장을
	// codgel cud(10); 이라는 문장을 쓸수 있지
	// 않을 까 싶은데
	// 적절하지 않다.
	// 왜냐하면 객체를 생성과 동시에 초기화하는
	// 효과를 지니는데
	// 클래스의 멤버는 생성과 동시에 초기화가 불가능하다
	// 자바나 씨샵은 가능하지만..
	// 클래스의 객체가 멤버로 존재하기 위해서는
	// 반드시 객체의 클래스는 void 생성자를 
	// 가져야 한다.
public:
	// 폴리스 클래스는 몽둥이 클래스의 객체를 
	// 포함하기 때문에
	// 자기가 가지고 있는 멤버의 스윙함수를 호출할
	// 수 있다.
	void UseWeapon(){ cud.Swing(); }
};

int main()
{
	// 다음과 같이 경찰 클래스의 객체 pol을 생성하면
	// 몽둥이 클래스를 포함하는 경찰 객체가 만들어지는데
	// 몽둥이 클래스의 객체인 cud도 객체이므로
	// 경찰 클래스와 몽둥이 클래스의 생성자가 모두 호출
	// 되어야 한다.
	//
	// 1. 경찰 객체를 위한 메모리 공간을 할당하면서
	// 2. 몽둥이 클래스를 위한 메모리 공간을 할당과 동시에
	// 3. 몽둥이 클래스의 생성자가 호출되고
	// 4. 경찰 클래스의 생성자가 호출된다.
	//
	// 명시적으로 어떤 생성자를 호출할지 
	// 선언되어 있지 않으므로 void 형태 생성자를 호출한다.
	// 즉, 클래스의 객체가 멤버가 포함되기 위해서는
	// 인자값을 받지않는 void 생성자를 포함해야한다.
	Police pol;
	
	pol.UseWeapon();

	return 0;
}

//
// 예제 2
//
#include <iostream>
using std::endl;
using std::cout;

class Cudgel  //몽둥이
{ 
public:
	void Swing(){ cout<<"Swing a cudgel!"<<endl; }
};


class Police //몽둥이를 소유하는 경찰
{
	Cudgel* cud;
public:
	Police(){
		// 객체를 동적으로 생성
		// 객체를 생성하면서 어떤 생성자를 호출할지
		// 선언이 없으므로 void 생성자를 호출
		// cud는 동적으로 생성된 몽둥이 객체를 
		// 가리키게 된다.
		cud=new Cudgel;
	}
	~Police(){
		delete cud;
	}
	void UseWeapon(){ cud->Swing(); }
};

int main()
{
	Police pol;
	pol.UseWeapon();

	return 0;
}

// has a (소유)관계는 상속에 의해서도 성립되고
// 대안의 방법으로도 성립이 되는데
// 보통은 대안의 방법을 권장한다.
// 상속의 경우는 두 클래스가 너무 긴밀하게
// 연결이 되어 있기 때문에..
// 상속은 느슨하면서도 확실한 관계가 좋은것.
// 즉, 필요한 경우 분리가 가능해야한다.
// 예제 2와 같이 사용하는게 좋다
// 예제 2가 약간 느슨하면서도 확실한 관계이다






'C언어' 카테고리의 다른 글

c++ 공부 요점정리 23  (0) 2013.12.04
c++ 공부 요점정리 22  (0) 2013.12.04
c++ 공부 요점정리 20  (0) 2013.11.27
c++ 공부 요점정리 19  (0) 2013.11.27
c++ 공부 요점정리 18  (0) 2013.11.27
Posted by 뮹실이

2013. 11. 27. 21:52 C언어

c++ 공부 요점정리 20






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
// =====================================================
// 35 세가지 형태의 상속
// =====================================================
//
// 접근 권한 변경
// : base 클래스의 멤버는 상속되는 과정에서 
// 접근 권한이 변경됨
// 다음과 같은 경우 b 클래스는 a 클래스로 상속되는
// 과정에서 접근권한이 변경되는데 
// 변경되는 방법이 public으로 하느냐
// protected, private로 하느냐는 결정...
//
class A : public B
{
...
}
//
// 대부분의 상속은 public 상속이다.
// public 상속에 포인트를 둔다.
// 
// 다음과 같이 protected 상속은
// protected 보다 접근권한이 넓은 것은
// protected 으로 맞춰서 상속하겠다는 의미
// 상속되는 과정에서 c는 public으로 선언되어 있어
// protected 보다 접근할수있는 범위가 넓다.
// 그러면 상속되면서 protected로 변경된다.
// b는 그대로 protected를 유지한다.
// a는 protected보다 접근 범위가 좁아서 
// 그대로 상속되는 것이 아니라
// private, protected, public 중 어느것도
// 포함되지 않는 접근불가로 바뀐다
// 즉 직접접근이 절대 허용되지 않는다.

class base
{
	private :
		int a;
	protected :
		int b;
	public :
		int c;	
}

class derived : protected base
{
	...
}
//
// protecte나 public은 private 보다 
// 접근 허용 범위가 넓기 때문에 
// 모두 private가 된다.
// a는 접근불가가 된다.
// 그래서 derived 클래스 내에서는 a로 직접접근이
// 불가능하게 된다.
// 
// 
//
class base
{
	private :
		int a;
	protected :
		int b;
	public :
		int c;	
}

class derived : private base
{
	...
}







'C언어' 카테고리의 다른 글

c++ 공부 요점정리 22  (0) 2013.12.04
c++ 공부 요점정리 21  (0) 2013.11.28
c++ 공부 요점정리 19  (0) 2013.11.27
c++ 공부 요점정리 18  (0) 2013.11.27
c++ 공부 요점정리 17  (0) 2013.11.27
Posted by 뮹실이
이전버튼 1 2 3 4 이전버튼

최근에 달린 댓글

05-18 07:19
Yesterday
Today
Total