C++ Static, Const, Explicit, Mutable
C++ static, const, explicit, mutable 에 대해 정리한다.
const
기본
-
변수 상수화
1 2 3 4 5
const int val1; // val1 = 10; !불가 const doule val2 = 20.0; // val2 = 30.0 !불가
-
포인터가 가리키는 데이터 상수화
1 2 3
int val1 = 10; const int * p = &val1; // *p = 20; !불가
-
포인터 자체 상수화
1 2 3 4 5
int val1 = 10; int val2 = 20; int const * p = &val1; *p = 20; // p = &val2; !불가
멤버변수
. 생성자 함수에 :
으로 연결된 멤버 이니셜라이져(member initializer)를 활용하여, 상수화 된 변수를 초기화 함
. 멤버 이니셜라이져는 생성자보다 먼저 실행됨
. const 멤버 변수가 아닌 일반 멤버 변수도 초기화가 가능함
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
#include <iostream>
using std::cout;
using std::endl;
class Student{
const int id;
int age;
char name[20];
char major[30];
public:
// 멤버 이니셜라이져 (member initializer)
Student(int _id, int _age, char * _name, char* _major) : id(_id), age(_age)
{
// id = _id; const int 이기 때문에 이 방법은 컴파일 오류
// age = _age; 일반 멤버변수도 멤버 이니셜라이져 방법으로 초기화 가능
strcpy(name, _name);
strcpy(major, _major);
}
void ShowData(){
cout << "학번: " << id << endl;
cout << "나이: " << age << endl;
cout << "이름: " << name << endl;
cout << "학과: " << major << endl;
}
};
int main()
{
Student K(201812345, 20, "Kim Young Mi", "Computer Science");
Student P(201878901, 21, "Park Chan Ki", "English");
K.ShowData();
cout << endl;
P.ShowData();
}
멤버함수
1
2
3
4
5
6
7
...
void ShowData() const
{
cout << "학번: " << id << endl;
...
}
...
. 멤버 함수가 상수화 되면
- 해당 함수를 통해 멤버 변수의 값이 변경되는 것이 허용되지 않음
- 상수화되지 않은 함수의 호출을 허용하지 않음
- 멤버 변수의 포인터를 리턴하는 것을 허용하지 않음
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
#include <iostream>
using std::cout;
using std::endl;
class Count{
int cnt;
public:
// 생성자, 초기화
Count() : cnt(0) {}
/* 상수화된 함수에서 포인터 리턴을 할 수 없으므로, 컴파일 에러
int * GetPtr() const {
return &cnt;
}
*/
// 리턴 포인터(포인터가 가리키는 값)를 상수화
// 따라서, 상수화된 함수 내에서 포인터 값을 리턴할 수 있음
// ※ 포인터를 상수화 시키려면 const int * GetPtr [확인 필요]
const int * GetPtr() const {
return &cnt;
}
void Increment(){
cnt++;
}
/* 상수화된 함수에서 상수화되지 않은 함수를 호출하므로, 컴파일 에러
void ShowData() const {
ShowIntro();
cout << cnt << endl;
}
void ShowIntro(){
cout << "count 값: " << endl;
}
*/
void ShowData() const {
ShowIntro();
cout << cnt << endl;
}
void ShowIntro() const {
cout << "count 값: " << endl;
}
};
int main()
{
Count count;
count.Increment();
count.ShowData();
return 0;
}
객체
. 객체의 멤버변수의 조작이 불가능함
. 상수화된 멤버 함수만 호출 가능
. 상수화된 멤버변수만 호출 가능
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
#include <iostream>
using std::cout;
using std::endl;
class Cal{
int num;
public:
Cal(int _num) : num(_num) {}
void Add(int n)
{
num += n;
}
void ShowData()
{
cout << num << endl;
}
};
int main()
{
const Cal cal1(10);
// cal1.Add(10); // const 객체로 인해 const 되지 않은 멤버변수 변경 불가
// cal1.ShowData(); // const 객체로 인해 const 되지 않은 멤버함수 호출 불가
return 0;
}
const화된 함수의 오버로딩
. 상수화된 함수인지, 아닌지
에 따라서 함수 오버로딩이 성립함
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
#include <iostream>
using std::cout;
using std::endl;
class Cal{
int num;
public:
Cal(int _num) : num(_num) {}
void ShowData()
{
cout << "void ShowData() 호출함 " << endl;
cout << "num: " << num << endl;
}
void ShowData() const {
cout << "void ShowData() const 호출함 " << endl;
cout << "num: " << num << endl;
}
};
int main()
{
const Cal cal1(10);
Cal cal2(20);
cal1.ShowData(); // 상수화된 객체로서, 상수화된 함수를 호출함
cal2.ShowData(); // 상수화되지 않은 객체로, 상수화되지 않은 함수를 호출함
return 0;
}
static
static 멤버의 특징
. 메인 함수가 호출되기 전에 메모리 공간에 올라가고, 초기화 됨
. Public으로 선언될 경우, 객체 생성 이전에도 접근이 가능함
. 선언 시, 클래스 내에 위치한다고 하여, 객체의 멤버로 존재하는 것이 아님. 다만 클래스 내에서 직접 접근할 수 있는 권한이 부여된 것
. “클래스 함수”, “클래스 변수” 가 정확한 표현
. 메모리의 데이터 영역에 올라감(전역변수와 같은 특징)
static 멤버 초기화
1
2
3
4
...
// int Classname::static_member_name=value_of_initilization;
int Person::count=1;
...
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
#include <iostream>
using std::cout;
using std::endl;
class First{
int val;
static int n; // private 선언, 외부접근이 불가능함
public:
First(int a=0){
val = a;
n++; // 내부접근은 가능
}
void ShowData(){
cout <<"val: "<<val<<endl;
cout <<"n: "<<n<<endl;
}
};
int First::n=1; // 전역변수(클래스 멤버변수) 초기화
int main(void)
{
First f1(20);
f1.ShowData();
First f2(40);
f2.ShowData();
return 0;
}
. 예제에서는 각 객체 내에는 변수 n이 멤버로 존재하지 않으며, 접근할 수 있는 접근 권한만 주어짐
explicit
. 명시적1 호출만을 허용
. 아래 예제에서 explicit
선언을 한 생성자에 대해서는, 묵시적2 호출을 허용하지 않아, 에러가 발생함
. explicit
선언은 객체 생성 관계를 분명히 하고자 하는 경우에 사용됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using std::cout;
using std::endl;
class First{
public:
explicit First(int a){
//First(int a){
cout << "explict First(int a)" << endl;
}
};
int main(void)
{
First first = 10; // 묵시적으로 First first(10); 으로 변환됨
return 0;
}
mutable
. const로 상수화된 멤버 함수에서 멤버 변수 조작을 위해 사용함
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
#include <iostream>
using std::cout;
using std::endl;
class mutable_test{
private:
mutable int val1;
int val2;
public:
// 생성자 멤버 변수 초기화
mutable_test() : val1(0), val2(0) {}
void SetData(int a, int b) const
{
val1 = a; // mutable val1 이므로 오류 없이 변경 가능
// val2 = b; // 상수화된 멤버함수는 멤버변수를 변경할 수 없음
}
void ShowData()
{
cout << "val1: " << val1 << endl;
cout << "val2: " << val2 << endl;
}
};
int main()
{
mutable_test m1;
m1.SetData(10, 20);
m1.ShowData();
return 0;
}