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

c++ 공부 요점정리 19






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
// =====================================================
// 34 멤버 이니셜라이저
// =====================================================
//
//
//
#include <iostream>
using std::endl;
using std::cout;

class Person
{
public:
	int age;
	char name[20];


	int GetAge() const {
		return age;
	}
	const char* GetName() const {
		return name;
	}

	Person(int _age=1, char* _name="noname"){
		age=_age;
		strcpy(name, _name);
	}
	
	~Person(){
		cout<<"~person() call"<<endl;
	}
};

class Student: public Person
{
	int num;
	char major[20]; //전공
public:
	// 학생 클래스의 생성자를 정의할 때
	// 사람 클래스의 생성자가 받을 인자를 
	// 전달 받도록 하면 
	// 사람클래스의 멤버 변수를 초기화 시킬 수 있다.
	// 그러나 이경우는 사람 클래스의 멤버 변수가 모두
	// public 일 경우에 가능하다
	// 그러나 정보은닉을 무너뜨리는 경우이므로
	// 적절치 않다.
	// 사람 클래스의 멤버 변수가 private 일경우는
	// 아래 생성자는 에러 발생
	// 비록 상속하지만 private이므로
	// 사람 클래스의 멤버 변수는 사람클래스 내에서만
	// 접근이 가능하기 때문
	// 다른 방법 필요
	// 멤버 이니셜라이저 : num이라는 인자를 a 로 
	// 초기화 시키는 방법
	// const 멤버를 초기화 시키는 방법이기도 하다
	// num 이라는 변수가 멤버 변수인 경우에는 
	// a로 초기화하라는 의미이지만 
	// num이 클래스의 이름인 경우에는 
	// a라는 인자값을 받을 수 있는 num 클래스의 생성자를
	// 호출하라라는 의미이다.
	// 즉, person(a)이면 사람 클래스에서 a를 전달 받을 수있는
	// 생성자를 호출하라라는 의미이다.
	// Student(int _age, char* _name, char* _major) : person(a, _name)
	// 위 문장과 같이 선언하면 
	// 사람 클래스의 멤버 변수도 원하는 형태로 초기화를 할 수 있다.
	//
	Student(int _age, char* _name, char* _major) : num(a)
	{
		age=_age;
		strcpy(name, _name);
		strcpy(major, _major);
	}
	const char* GetMajor() const {
		return major;
	}
	void ShowData() const {
		cout<<"이름: "<<GetName()<<endl;
		cout<<"나이: "<<GetAge()<<endl;
		cout<<"전공: "<<GetMajor()<<endl;
	}
	
	~Student(){
		cout<<"~Student() call"<<endl;
	}
};

int main(void)
{
	Student Kim(20, "Hong Gil Dong", "computer");
	Kim.ShowData();

	return 0;
};

// 지금까지는 객체 생성 순서와 방법에 대해 알아봤다.
// 다음은 소멸 순서에 대해 진행
// 
// main 함수가 호출이 끝나는 순간에 
// 지역 객체인 kim도 소멸된다.
// kim은 사람클래스를 상속하는 학생 클래스이므로
// 학생 클래스의 소멸자만 호출되는게 아니라
// 사람 클래스의 소멸자도 호출된다.
// 소멸자의 호출 순서는 다음과 같다
// 1. derived 객체 소멸자 호출
// 2. base 객체 소멸자 호출
// 3. 메모리 반환
// 
//
//
// protected 멤버
// : private와 public의 중간 정도의 접근 범위를 지니는 키워드
//   public 보다는 접근 범위가 좁고
//   private 보다는 접근 범위가 넓음
//   상속관계에 놓여있을 경우 접근을 허용
//   기본적으로 private와 성질이 거의 동일하지만
//   private 같은경우 상속관계에서도 접근을 허용하지 않지만
//   protected 는 상속관계일 경우 접근가능하다
//   상속되어지는 클래스의 protected 멤버 변수를
//   상속하는 클래스에서 접근이 가능
//   
#include <iostream>
using std::endl;
using std::cout;

class Person
{
protected:
	int age;
	char name[20];
public:

	int GetAge() const {
		return age;
	}
	const char* GetName() const {
		return name;
	}

	Person(int _age=1, char* _name="noname"){
		age=_age;
		strcpy(name, _name);
	}
};

class Student: public Person
{
	char major[20]; //전공
public:
	Student(int _age, char* _name, char* _major)
		: Person(_age, _name)
	{
		strcpy(major, _major);
		//
		// 사람 클래스의 멤버 변수가 protected 이므로
		// 다음과 같이 학생 클래스의 생성자에서
		// 직접 초기화가 가능하지만
		// 멤버 이니셜라이저를 사용하는게 
		// 더 좋은 구조이다.
		// 왜냐하면
		// 만약
		// 사람 클래스의 멤버 변수의 수정이 발생할 경우
		// 학생 클래스의 수정도 필요로하게 된다.
		// 직접 초기화하지 않았다면 사람클래스만 수정하면
		// 될일을...
		// 그래서 멤버 이니셜라이저를 사용하면
		// 이런 일이 발생하지 않는다.
		// 즉, 클래스의 멤버 변수 초기화는 
		// 그 멤버 변수가 속한 클래스의 생성자에서
		// 초기화하는것이 가장 좋다.
		//
		strcpy(name, _name);
	}
	const char* GetMajor() const {
		return major;
	}
	void ShowData() const {
		cout<<"이름: "<<age<<endl;
		cout<<"나이: "<<name<<endl;
		cout<<"전공: "<<major<<endl;
	}
};

int main(void)
{
	Student Kim(20, "Hong Gil Dong", "computer");
	Kim.ShowData();

	return 0;
};










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

c++ 공부 요점정리 21  (0) 2013.11.28
c++ 공부 요점정리 20  (0) 2013.11.27
c++ 공부 요점정리 18  (0) 2013.11.27
c++ 공부 요점정리 17  (0) 2013.11.27
c언어 파일 저장 및 로드 예제 2  (0) 2013.11.27
Posted by 뮹실이

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

c++ 공부 요점정리 18






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
// =====================================================
// 33 상속의 기본 개념
// =====================================================
//
class AAA // base 클래스
{
	int a;
	
	public :
		AAA(){
			cout<<"AAA() call"<<endl;
			a = 10;
		}
		AAA(int i){
			cout<<"AAA(int i) call"<< endl;
		}
}

// class BBB : public AAA
// 이문장의 의미는
// aaa 클래스는 bbb 클래스에 의햇
// public 상속되어 진다.
// 보통 상속이 되어지는 클래스를
// base 클래스, ..., 등등으로 불리고
// 상속을 하는 클래스를
// derived 클래스, ..., 등등으로 불린다.

class BBB : public AAA // derived 클래스
{
	int b;
	
	public :
		BBB(){
			cout<<"bbb() call"<< endl;
			b = 20;
		}
		BBB(int i){
			cout<<"bbb(int i) call"<< endl;
		}
}

// aaa 클래스를 상속하는 bbb 클래스를 생성할 때도
// 객체 생성과 동일한 과정을 거친다.
// 1. 메모리 공간 할당
// 2.0 derived 클래스의 생성자 호출
// 2.1 base 클래스의 생성자 호출 및 실행
// 2.2 derived 클래스의 생성자 실행
//
// main 함수에서 bbb 클래스의 객체인 b를
// 생성하면 b를 위해 메모리를 할당한다
// bbb 클래스의 멤버만을 위한 메모리 할당이 아니라
// 상속하는 aaa 클래스의 멤버도 고려되어 메모리가
// 할당된다.
// bbb 클래스를 위한 메모리 공간을 할당하고
// bbb 클래스의 생성자를 호출하러간다.
// bbb 클래스의 생성자 호출은 이루어지나
// 아직 실행은 되지 않는다
// 보통은 함수는 호출과 동시에 실행되지만
// 이경우는 다르다
// bbb 클래스의 생성자를 호출하고난 후
// 생성자를 실행하지 않고 
// aaa 클래스의 생성자를 실행하러 간다.
// 어떤 aaa 클래스의 생성자를 호출하라는 
// 말이 없없으므로 aaa 클래스의 void 생성자를
// 실행하러 간다.
// 그래서 a 는 10으로 초기화가 되고
// aaa 클래스의 호출 및 실행이 끝나면 
// bbb 클래스의 생성자가 실행된다.
// b 는 20으로 초기화 된다.
// b는 멤버로서 멤버 a를 가지지 않지만
// a클래스를 상속함으로 인해서
// b 객체 안에는 a 클래스 멤버가 존재한다.
// a 클래스의 생성자도 호출되어진다.
// 왜 bbb 클래스의 생성자를 실행하는 과정에서
// aaa 클래스의 생성자를 호출하는 이유는 무엇인가?
// bbb 클래스의 멤버는 bbb 클래스의 생성자 내에서
// 초기화되는 것이 가장 이상적이다
// 즉, bbb 클래스 보다는 aaa 클래스가 먼저 정의되어있으므로
// aaa 클래스의 생성자는 aaa 클래스의 멤버를 적절히 초기화하도록
// 정리되어 있을것이므로 aaa 클래스의 생성자로 초기화하는 것이
// 따라서 bbb 클래스의 내에서 aaa 클래스의 멤버를 초기화하는것보다
// 더 적절할 것이다.
// 
void main()
{
	BBB b;
}

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

class Person
{
	int age;
	char name[20];
public:

	int GetAge() const {
		return age;
	}
	const char* GetName() const {
		return name;
	}

	// 디폴트 매개변수가 설정되어 있으므로
	// 인자값을 두개받는 생성자이자
	// void 생성자라고도 할수 있다.
	Person(int _age=1, char* _name="noname"){
		age=_age;
		strcpy(name, _name);
	}
};

class Student: public Person
{
	char major[20]; //전공
public:
	Student(char* _major){
		strcpy(major, _major);
	}
	const char* GetMajor() const {
		return major;
	}
	//
	// 학생 클래스 내에는 겟네임이라는 함수가 없다.
	// 겟네임 호출할 수 있는 이유는
	// 학생 클래스가 사람 클래스를 상속하고 있기 때문
	//
	void ShowData() const {
		cout<<"이름: "<<GetName()<<endl;
		cout<<"나이: "<<GetAge()<<endl;
		cout<<"전공: "<<GetMajor()<<endl;
	}
};

//
// student 클래스의 객체인 kim을 생성하면서
// 인자값으로 computer 라는 문자열을 전달
// student 클래스의 객체를 위한 메모리 공간을
// 사람 클래스의 멤버를 상속하기 위한 공간까지
// 계산해 kim에 메모리 할당하면서
// 학생 클래스의 생성자를 호출
// 학생 클래스는 사람 클래스를 상속하고 있기 때문에
// 사람 클래스의 생성자를 호출 및 실행한다.
// 어떤 생성자를 호출할지 정보가 없기 때문에 
// 사람 클래스의 void 생성자를 호출 및 실행한다.
// 그리고 학생클래스의 생성자 몸통부분이 실행된다.
// 지금의 예제는 aaa 클래스의 멤버 변수 초기화시
// 원하는 값으로 초기화 시키지 못하는 문제가 있다.
// 그 문제를 해결하는 방법으로는
// 멤버 이니셜라이져가 있다.
// base 클래스의 생성자를 명시적으로 호출하는것이다.

int main(void)
{
	Student Kim("computer");
	Kim.ShowData();

	return 0;
};







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

c++ 공부 요점정리 20  (0) 2013.11.27
c++ 공부 요점정리 19  (0) 2013.11.27
c++ 공부 요점정리 17  (0) 2013.11.27
c언어 파일 저장 및 로드 예제 2  (0) 2013.11.27
c언어 파일 관련 함수  (0) 2013.11.27
Posted by 뮹실이

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

c++ 공부 요점정리 17







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
// =====================================================
// 32 상속으로 들어가기에 앞서서
// =====================================================
//
// 
//
#include <iostream>
using std::endl;
using std::cout;

// entity 클래스(데이터)
class Permanent
{
private:
	char name[20];	
	int salary;
public:
	Permanent(char* _name, int sal);
	const char* GetName();
	int GetPay();
};

Permanent::Permanent(char* _name, int sal) {
	strcpy(name, _name);
	salary=sal;
}
const char* Permanent::GetName()
{
	return name;
}	
int Permanent::GetPay()
{
	return salary;
}

// 컨트롤 클래스
class Department
{
private:
	Permanent* empList[10];
	int index;
public:
	Department(): index(0) { };
	void AddEmployee(Permanent* emp);
	void ShowList();
};

void Department::AddEmployee(Permanent* 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;
}








Posted by 뮹실이






#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>


int main()

{

double d[10]={

1.1, 2.2, 3.3, 4.4, 5.5,

6.6, 7.7, 8.8, 9.9, 10.1

};

ddd d2;


FILE *fp;

int i;


if((fp=fopen("myfile.dat","wb"))==NULL){

printf("cannot open file");

exit(1);

}


for(i=0;i<10;i++)

if((fwrite(&d[i],sizeof(double),1,fp))!=1){

printf("write error");

exit(1);

}


fclose(fp);


if((fp=fopen("myfile.dat","rb"))==NULL){

printf("cannot open file");

exit(1);

}


for(i=0;i<10;i++)d[i]=-1.0;


if (!feof(fp))

{

for(i=0;i<10;i++)

if(fread(&d[i],sizeof(double),1,fp)!=1){

printf("read error");

exit(1);

}

}


fclose(fp);

for(i=0;i<10;i++)printf("%f\n",d[i]);


return 0;

}







Posted by 뮹실이







ftell : 파일 읽기 시 파일 포인터 위치이동시키는 함수

rewind : 파일 포인터 위치를 처음위치로 되돌리는 함수

fseek

file_exists : 파일이 존재하는지 확인하는 함수









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
86
87
88
89
90
91
92
//##########################################
//
//					define
//
//##########################################
FILE		*file_pointer;
char 		File_Name[] 	= "";
Load_Type 	load_data;
int 		line_num 		= 0;
int 		total_line_num	= 0;


void main()
{
//##########################################
//
//					save
//
//##########################################
	int max_line_size = 9999999;
	char line_buff[max_line_size];

	sprintf(File_Name,"record_%d.dat",0);

	if ((file_pointer = fopen(File_Name, "w")) != NULL)
	{
		fprintf(file_pointer,"%15.6f, %15.6f, %15.6f, %6.3f, %6.3f, %6.3f\n"
				, data.Position_X
				, data.Position_Y
				, data.Position_Z
				, data.Roll
				, data.Pitch
				, data.Yaw);
		printf("%15.6f, %15.6f, %15.6f, %6.3f, %6.3f, %6.3f\n"
				, data.Position_X
				, data.Position_Y
				, data.Position_Z
				, data.Roll
				, data.Pitch
				, data.Yaw);

		fclose(file_pointer);
	}

//##########################################
//
//					load
//
//##########################################

	sprintf(File_Name,"record_%d.dat",0);

	if ((file_pointer = fopen(File_Name, "r")) != NULL)
	{
		while(fgets(line_buff,max_line_size, file_pointer) != NULL)
		{
			total_line_num++;
			if (line_buff[0] == '\0' || line_buff[0] == EOF) total_line_num--;
		}
		rewind(file_pointer);

		if (feof(file_pointer) == 0)
		{
			memset(&load_data,0,sizeof(load_data));
			fscanf(file_pointer,"%lf",&load_data.Position_X);
			fscanf(file_pointer,", %lf",&load_data.Position_Y);
			fscanf(file_pointer,", %lf",&load_data.Position_Z);
			fscanf(file_pointer,", %lf",&load_data.Roll);
			fscanf(file_pointer,", %lf",&load_data.Pitch);
			fscanf(file_pointer,", %lf",&load_data.Yaw);
			line_num++;

			printf("%5d,%5d %15.6f, %15.6f, %15.6f, %6.3f, %6.3f, %6.3f\n"
					,total_line_num
					,line_num
					,load_data.Position_X
					,load_data.Position_Y
					,load_data.Position_Z
					,load_data.Roll
					,load_data.Pitch
					,load_data.Yaw);
		}
		else if (feof(file_pointer) != 0)
		{
			//fseek(file_pointer,0,SEEK_SET);
			rewind(file_pointer);
			line_num = 0;
		}

	fclose(file_pointer);
	}
}









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

c언어 파일 저장 및 로드 예제 2  (0) 2013.11.27
c언어 파일 관련 함수  (0) 2013.11.27
c++ 공부 요점정리 16  (0) 2013.11.23
c++ 공부 요점정리 15  (0) 2013.11.23
c++ 공부 요점정리 14  (0) 2013.11.23
Posted by 뮹실이

2013. 11. 23. 21:14 C언어

c++ 공부 요점정리 16








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
// =====================================================
// 31 explicit and mutable
// =====================================================
//
// explicit
// : 명시적 호출만 허용한다.
//
#include<iostream>
using std::cout;
using std::endl;

class AAA
{
public:
    explicit AAA(int n){
		cout<<"explicit AAA(int n)"<<endl;
	}
};

int main(void)
{
	// 이문장은 c 스타일의 문장으로써
	// 묵시적으로 AAA a1(10); 와 같이 
	// 형변환이 되어서 객체 생성이 완료되는것
	// 즉 묵시적으로 생성자를 호출하는 것이다.
	// 그런데 생성자가 explicit로 선언되어 있으면
	// 묵시적 호출이 허용되지 않으므로 
	// 컴파일시 오류 발생
	AAA a1=10; 
	// AAA a1=10; 이 문장은 묵시적으로 변환되지만
	// 혼란을 초래 할 수 있기 때문에 권장되지 않는다
	// 따라서 생성자에 explicit를 선언함으로써
	// 혼란을 초래하는 문장에서 컴파일 오류를 발생시켜
	// 예방할수있다.
	
	AAA a1(10); // 생성자를 명시적으로 호출

	return 0;
}


// mutable
// : const에 예외를 둔다
//  별로 유용하지도 않고
//  사용을 권장하지 않는다.
//
#include<iostream>
using std::cout;
using std::endl;

class AAA
{
private:
	mutable int val1;
	int val2;

public:
	// setdata가 상수화 되어있어서
	// 멤버 조작이 불가능하다
	// 그러나 mutable 선언이 되어있는
	// val1은 조작이 가능하다
	// 즉 const에 예외를 둔다...
	// 
	void SetData(int a, int b) const 
	{
		val1=a;  // val1이 mutable이므로 OK!
		val2=b;  // Error!
	}
};

int main(void)
{
	AAA a1;
	a1.SetData(10, 20);
	return 0;
}









Posted by 뮹실이

2013. 11. 23. 20:37 C언어

c++ 공부 요점정리 15








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
// =====================================================
// 30 클래스와 static
// =====================================================
//
// 보통 c에서 static을 선언 할때는
// 지역변수에 선언한다 전역으로 선언해도 되는데
// static으로 선언하면서 지역에 선언하는 이유는
// static으로 선언함으로써 전역변수의 특징을
// 가지면서 변수의 접근에 제한을 두기 위해서
//
// static 멤버의 등장
// : 전역 변수와 전역 함수를 일부 대체하기 위해서 등장
//
// static 키워드의 효과
// : 모든 객체가 공유할 수 있는 멤버
//

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

class Person
{
	char name[20];
	int age;
	
	// static 선언
	// static으로 선언함으로써
	// 모든 객체가 공유가능
	// person 클래스 위에 전역으로 선언한것과
	// 동일한 효과를 낸다
	static int count;
public:
	Person(char* _name, int _age)
	{
		strcpy(name, _name);
		age=_age;
		cout<<count++<<"번째 Person 객체 생성"<<endl;
	}
	void ShowData(){
		cout<<"이름: "<<name;
		cout<<"나이: "<<age;
	}
};

int Person::count=1; // static 멤버 초기화

int main(void)
{
	Person p1("Lee", 13);
	Person p2("Hong", 22);

	return 0;
}

// static 멤버의 특징
// : 클래스 변수, 클래스 함수라 부른다.
//   static 멤버라 부르지 않는다.
//   (객체를 생성했을 때 객체의 멤버로 존재하는게
//   아니라 클래스 내에 선언이 되어서 클래스로 
//   선언되는 모든 객채가 모두 공유하기 때문에
//   즉, 객체 단위로 사용되는게 아니라 
//   클래스 단위로 사용이 되기 때문에 
//   클래스 변수, 클래스 함수라 부른다.)
//   main 함수 호출 이전에 메모리 공간에 올라가서
//   초기화된다(전역변수와 동일)
//   선언된 클래스의 객체 내에 직접 접근 허용
//   static 멤버 초기화문으로 초기화 해야한다.
//   
class AAA
{
	int val;
	//
	// 클래스 내에서 static으로 선언함으로써
	// 
	static int n;
	public:
	// 생성자에서 static으로 선언된 변수를 
	// 초기화하면 객체가 생성될때마다 초기화가
	// 되므로 생성자 내에서 초기화 하면 안된다.
	// 그래서 static 멤버 초기화 문장을 사용해야한다
	AAA(int a = 0){
		val = a;
		n++;
	}
	void showdata(){
		...
	}
}

// static 클래스 변수는 반드시 초기화를 
// 해야하는데 다음과 같은 
// static 멤버 초기화 문장을 이용해 초기화한다
// AAA 클래스 안에 static으로 선언된 변수 n을
// 1로 초기화한다는 뜻
// 또한 객체가 생성되기 이전에 메모리 공간에
// 올라간다 따라서 생성자로 초기화 할수도 없다
//
int AAA::n = 1;

int main(void)
{
	// 만약 static int n 이 private로 선언되지않고
	// public으로 선언되었다면
	// 객체가 생성되기 이전에
	AAA::n = 1;
	// 을 해도 문제가 되지 않는다
	// static으로 선언되었기 때문에
	// 객체가 생성되기 이전에 메모리에 
	// 할당되어 있기 때문
	//
	// 이렇게 클래스 내부가 아니라 main 함수처럼
	// 외부에서 static 변수로 접근할 때는
	// 클래스의 이름을 명시하고 범위지정연산자(::)를
	// 사용해 접근해야하지만
	// 클래스 내에서는 직접접근 권한이 있기때문에
	// 단순히 n = 10; 과 같이 사용할 수 있다.
	//
	// 만약 private로 선언되면 가려지기 때문에
	// 접근제한이된다.
	
	AAA a1(10);
	a1.showdata();
	
	AAA a2(20);
	a2.showdata();
	return 0;
}










Posted by 뮹실이

2013. 11. 23. 20:06 C언어

c++ 공부 요점정리 14








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
// =====================================================
// 29 클래스와 const
// =====================================================
//
// const 객체
// : 데이터의 변경이 허용되지 않는 객체
//    const 함수 이외에는 호출 불가
//
const int i = 10; // const 변수
const AAA a(10); // const 객체

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

class AAA
{
	int num;
public :
	AAA(int _num) : num(_num) {}
	void Add(int n){
		num+=n;
	}
	void ShowData(){
		cout<<num<<endl;
	}
	//
	// 해결방법
	//
	//void ShowData(){
	//	cout<<num<<endl;
	//}
};

int main()
{
	const AAA aaa(10);
	
	// const 객체이기 때문에 
	// 멤버 변수 변경이 불가능하므로
	// 컴파일시 에러 발생
	aaa.Add(10);  // Compile Error
	
	// const 객체인데
	// showdata 함수가 상수화 되어 있지 않기 때문에
	// 멤버 변수를 조작할 가능성이 있어서 
	// 컴파일시 에러 발생
	// 컴파일러는 함수가 멤버 변수를 조작하는지
	// 검사하는게 아니라 
	// 함수가 상수화 되었는지 아닌지를 검사해
	// 멤버 변수 조작의 가능성을 확인하기 때문에
	// 실제 상수화 되지 않은 함수에서
	// 멤버 변수를 조작하지 않더라도
	// 컴파일시에는 에러가 발생한다.
	// 해결방법으로는
	// showdata에서는 멤버 변수를 조작할 
	// 필요가 없으므로 함수를 const 선언으로
	// 상수화 해준다
	//
	// 즉, const 객체는 const 함수 이외에 호출 불가
	//
	aaa.ShowData();  // Compile Error

	return 0;
}

// 
// const와 함수 오버로딩
// : const도 함수 오버로딩 조건에 포함된다.
//
void func(int n) const {...}
void func(int n) {...}

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

class AAA
{
	int num;
public :
	AAA(int _num) : num(_num) {}

	void ShowData(){
		cout<<"void ShowData() 호출"<<endl;
		cout<<num<<endl;
	}
	void ShowData() const {
		cout<<"void ShowData() const 호출"<<endl;
		cout<<num<<endl;
	}
};

int main()
{
	const AAA aaa1(20);
	AAA aaa2(70);
	
	// 자동으로 상수화된 showdata을 호출
    aaa1.ShowData(); 
	
	// 자동으로 상수화되지 않은 showdata을 호출
	aaa2.ShowData(); 
	return 0;
}








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

c++ 공부 요점정리 16  (0) 2013.11.23
c++ 공부 요점정리 15  (0) 2013.11.23
c++ 공부 요점정리 13  (0) 2013.11.23
c++ 공부 요점정리 12  (0) 2013.11.23
c++ 공부 요점정리 11  (0) 2013.11.21
Posted by 뮹실이

2013. 11. 23. 00:08 C언어

c++ 공부 요점정리 13








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
// =====================================================
// 28 클래스와 const
// =====================================================
//
const double PI = 3.14;
PI = 3.1315; // 컴파일 오류


//
// 포인터 선언시 데이터 상수화
//
// pN이 가리키는 대상을 상수화
// pN이라는 포인터를 통해 접근할 경우에만
// 값의 변경을 허용하지 않음
//
int n = 10;
const int* pN = &n;
n = 30;
*pN = 20; // 커파일 오류


//
// 포인터 선언시 포인터 상수화
//
// pN이라는 포인터 자체를 상수화한다
// pN은 n1만 가리켜야한다
// 가리키는 대상을 바꿔 다른 대상을 가리키지 못한다.
//
int n1 = 10;
int n2 = 20;
int* const pN = &n1;
*pN = 20;
pN = &n2; // 컴파일 오류

//
// 멤버 변수의 상수화, 그리고 초기화의 예제
//
// class의 객체를 생성시 1. 메모리를 항당하고
// (메모리의 값들은 쓰레기 값으로 채워져있다.)
// 2. 생성자에 의해 초기화된다.
//
class Student
{
	// 메모리 할당시 쓰레기 값으로 채워져있는데
	// const 로 선언하면 나중에 생성자가 
	// 값을 변경하지 못하므로 에러 발생
	// 그럼 클래스에서는 const를 사용하지 못하느냐
	// 그래서 등장한 문법적 요소가 
	// 멤버 이니셜라이저(member initializer)
	// 생성자의 선언부와 몸체부 사이에
	// :id(_id) 라고 선언해주면
	// 멤버 변수 id에 전달 인자 _id의 값을 대입한다
	// :id(_id) 이 부분은 생성자가 호출되기 이전에 
	// (생성자의 몸체부분이 실행되기 이전에)
	// 완료가 된다.
	// 즉 const 멤버 변수를 초기화 시켜주기위한
	// 예외적인 문법
	const int id; 
	int age;
	char name[20];
	char major[30];
public:
	Student(int _id, int _age, char* _name, char* _major)
	{
		id=_id;
		age=_age;
		strcpy(name, _name);
		strcpy(major, _major);
	}
};
// Student(int _id, int _age, char* _name, char* _major)는
// 생성자의 선언부이고
// {}의 내용은 생성자의 몸체부이다.


//
// const 멤버 함수
//
// 멤버 함수가 상수화 되면 그 멤버 함수가 속해있는
// 클래스의 멤버 변수 값 변경을 허용하지 않는다.
// 멤버 변수 값의 변경에 대한 기회제공도 불가능하다
//
// 예제 1
//
class Student
{
	const int id;
	int age;
	char name[20];
	char major[30];
public:
	Student(int _id, int _age, char* _name, char* _major):id(_id), age(_age)
	{
		strcpy(name, _name);
		strcpy(major, _major);
	}

	// showdata라는 함수를 상수화
	// 함수 몸체부분과 함수 선언부 사이에
	// const를 선언한다.
	// 멤버변수 변경이 불가능하다
	// 변경시 컴파일 에러 발생
	// 여기서는 멤버변수를 변경하지 않고
	// 출력하기 위해서 참조만 하고 있다
	void ShowData() const
	{
		cout<<"이름: "<<name<<endl;
		cout<<"나이: "<<age<<endl;
		cout<<"학번: "<<id<<endl;
		cout<<"학과: "<<major<<endl;
	}
};


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

class Count
{
	int cnt;
public :
	Count() : cnt(0){}
	
	// 멤버 함수가 상수화되면
	// 멤버 변수의 직접적인 조작만 불가능한것이 아니라
	// 멤버 변수를 조작할 수 있는 기회제공도 허용이 안된다
	// cnt 값을 직접적으로 조작하고 있지는 않지만
	// 멤버 변수의 포인터를 리턴해주고있다.
	// cnt 포인터를 통해 값을 변경할 수 있기때문에
	// 멤버변수를 조작할 기회를 제공하는 것이다.
	// 그래서 컴파일 에러가 발생한다.
	// 이런 경우에는 const 키워드를 빼는게 아니라
	// 멤버 변수의 포인터를 리턴하되
	// 리턴하는 포인터의 데이터를 상수화시켜
	// 리턴하는 포인터를 이용해서는
	// 멤버변수를 변경할 수 없고 참조만 가능하도록 한다.
	int* GetPtr() const{
		return &cnt;  // Compile Error
	}
	// 위 함수를 다음 함수로 수정하면
	// 컴파일에러가 발생하지 않는다.
	const int* GetPtr() const{
		return &cnt;
	}

	void Increment(){
		cnt++;
	}

	// 컴파일시 컴파일러가 인식하는 방법은
	// showdata는 상수화된 함수이다.
	// 그래서 함수내에서 멤버 변수를 조작하는지 검사하는데
	// showintro를 호출하네
	// showintro는 상수화 되지 않은 함수이다.
	// showintro로 가서 멤버 변수를 조작하는지 검사하는게 아니라
	// showintro가 상수화된 함수인지 아닌지 검사
	// 만약 showintro가 상수화된 함수이면 멤버 변수 조작을
	// 하지 않는게 확실하지만
	// 상수화된 함수가 아니면 멤버 변수를 조작할 
	// 가능성이 있기 때문에 컴파일 에러가 발생한다.
	// 컴파일 에러 해결 방법은 
	// showintro 함수가 멤버 변수 조작을 하지 않는 함수이므로
	// 함수를 상수화 시켜 멤버변수 조작의 가능성을 
	// 제거 하면 컴파일 에러가 발생하지 않는다.
	void ShowData() const {
		ShowIntro();  // Compile Error
		cout<<cnt<<endl;		
	}
	void ShowIntro() {
		cout<<"현재 count의 값 : "<<endl;
	}
};

int main()
{
	Count count;
	count.Increment();
	count.ShowData();

	return 0;
}










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

c++ 공부 요점정리 15  (0) 2013.11.23
c++ 공부 요점정리 14  (0) 2013.11.23
c++ 공부 요점정리 12  (0) 2013.11.23
c++ 공부 요점정리 11  (0) 2013.11.21
c++ 공부 요점정리 10  (0) 2013.11.21
Posted by 뮹실이
이전버튼 1 2 3 4 이전버튼

최근에 달린 댓글

05-22 11:00
Yesterday
Today
Total