Efficient Programming in C++
저번 Static설명에 이어서 설명을 시작하도록 하겠습니다. 만약, static글 읽어보지 못하신 분은 아래 링크 타고 들어가셔서 정적 변수에 관한 내용을 읽고 오시는 것을 추천드립니다.
[C++] static, const, explicit 제대로 알고 사용하기![1]
Powerful Language C++ C++에서 static, const, explicit이라는 생소할 수도 있고 생소하지 않을 수도 있는 키워드가 존재합니다. 하지만, 뭐 무조건 이걸 써야 한다 이런 개념은 아니지만, 위와 같은 키워드를
hazarddev.tistory.com
"Constant"
우린 이미 영단어로써 이 뜻을 알고 있습니다. 상수라는 뜻이라는 건 모두가 알지 않을까 생각합니다. 상수는 한번 정의되면 C/C++에서는 수정을 절대 절대 할 수 없습니다. 하려고 한다면, 컴파일러 레벨에서 분명한 거부 사인을 프로그래머에게 전달하기 때문입니다. 물론 다른 언어에서도 const가 있으나, 저희가 알고자 하는 것은 C++에서의 const죠! 여하튼 프로그램에서 고정된 변수의 값입니다. 다양한 상수 변수를 생각할 수 있습니다. int, double, long, float, short, char 등 많은 유형의 상수 타입 변수를 생성할 수 있습니다. 그러니까 const int argv = 10; 이나 const char argv = "hello"; 등 많은 방식으로 선언할 수 있으며, 리터럴 형태로 말하기도 합니다. 그렇다면 예제를 통해서 알아보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
|
int
main()
{
const int num1 = 10;
const int num2 = 20;
cout << num1 + 1 << endl;
cout << num1 + num2 << endl;
//num1 = 20; <--- can't assign
return 0;
}
|
cs |
보시다시피, const키워드를 사용해서 선언한 변수 같은 경우는 새로운 대입이 불가능하다는 것을 알 수 있습니다. 컴파일러레벨에서 막기 때문에 이는 컴파일 자체가 불가능합니다. 그렇다면 함수 및 클래스에서의 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
|
class Foo{
private:
int var;
public:
Foo(){var = 10;}
void show() const;
void changeVal() const;
};
void Foo::changeVal() const{
// var = 12; <--- can't assign new value
//member function is const function so,
//can't change member variables
}
void Foo::show() const {
cout << var << endl;
}
int
main()
{
Foo foo;
foo.show();
return 0;
}
|
cs |
두개의 멤버 함수가 선언되었다는 것을 알 수 있습니다. 하나는 var를 출력하는 함수와 var의 값을 변경하는 함수입니다. 하지만 하나는 동작하지만 하나는 컴파일 영역에서 거부된다는 것을 알 수 있습니다. 이유로는 함수에 const가 붙게 되면, 선언된 함수 영역에서 값을 변경하지 않겠다는 의미이기 때문입니다. 값을 변경하지 않는 선에선 단순 대입 복사 정도는 가능하지만, 값을 새로 할당하거나 증감 연산은 불가능합니다.
1
2
3
4
5
6
|
#define MAX 1000
void changeVal2(){
//MAX += 2; <--- define preprocessing keyword variables
//can't assign new value or binary operand
}
|
cs |
또한 define 전처리기 문으로 작성된 값 또한 const변수와 같이 고정된 값입니다. 컴파일러는 소스파일에서 식별자에 대한 토큰 문자열을 대체합니다. 그러니까 컴파일 영역에서 메모리를 할당하는 것이 아닌 define 매크로로 정의된 매개변수를 컴파일러가 다른 영역(함수 혹은 클래스) 등에서 만났을 때 그때그때 값을 할당해주기 때문입니다. 그렇기 때문에 const변수는 메모리를 확인 가능하나 define은 확인할 수 없다는 차별점을 가지고 있습니다.
Static const var
그렇다면 저번 시간에 설명드린 static키워드와 const키워드를 동시에 사용하는 예제 또한 보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
static const int foo = 1000;
class mini{
static const int bar = 100;
public:
mini(){}
void op()const{
int temp = 10;
while (temp != 0){
cout << bar - temp << endl;
temp--;
}
}
};
int
main()
{
//foo = 12; <--- can't assign new value
cout << foo << endl;
mini m;
m.op();
return 0;
}
|
cs |
값을 새로 할당하는 것은 안되지만 아무 값도 반환하지 않고, 변경하지 않는 이항 연산은 가능하다는 것을 알 수 있습니다. 정적 변수를 저번 시간 때 설명드렸듯이, 객체가 생성되기 전 컴파일러는 이미 정적 변수에 대한 메모리를 할당합니다. 자세한 설명은 위 링크 static에 대한 설명을 보는 것을 추천드립니다. 여하튼 그렇기 때문에 아래 연산들이 가능한 것입니다. 정리드리자면, static const var = 10;은 불변 타입의 정적 변수 var의 값 10 이렇게 고정된다고 이해를 하는 편이 가장 이상적이라고 생각합니다.
Explicit
explicit는 말 그대로 명시적 즉, 명시적인 ~다라는 개념의 키워드입니다. 그렇기 때문에 개발자가 선언한 객체의 형 변화를 막는 데 사용하는 키워드이며, 형 변환을 강제로 제한합니다. 이렇게 설명하면 감이 잘 오지 않기 때문에 아래 코드를 보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Vector{
private:
double x, y;
public:
Vector(double i=0.0, double j=0.0):x(i),y(j){}
void show () const{
cout << "x val : " << x << " " << "y val : " << y << endl;
}
bool operator == (Vector vec){
return vec.x == x && vec.y == y ? true : false;
}
};
int
main()
{
Vector vector(3.0, 0.0);
if (vector == 3.0){
cout << "It's same value" << endl;
}else{
cout << "Diff" << endl;
}
return 0;
}
|
cs |
조금 어려운 부분이 존재할 수 있으나 잘 보시기 바랍니다. Vector객체는 3.0과 0.0의 값으로 초기화되었다는 것을 알 수 있습니다. 그리고 생성자에서 명시적인 형변환을 진행하지 않았기 때문에 if 조건문에서의 vector == 3.0은 마치 vector == (Vector) 3.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
|
class Vector{
private:
double x, y;
public:
explicit Vector(double i=0.0, double j=0.0):x(i),y(j){}
void show () const{
cout << "x val : " << x << " " << "y val : " << y << endl;
}
bool operator == (Vector vec){
return vec.x == x && vec.y == y ? true : false;
}
};
int
main()
{
Vector vector(3.0, 0.0);
if (vector == 3.0){ // invalid operands to binary expression
//because Vector and double is different type object
cout << "It's same value" << endl;
}else{
cout << "Diff" << endl;
}
return 0;
}
|
cs |
같은 코드라고 생각될 수 있으나 자세히 보면 완전히 다릅니다. Vector Constructor는 explicit키워드를 사용해서 선언되었기 때문에 명시적으로 자신만의 타입을 가집니다. 그렇기 때문에 컴파일 시도 시 아래와 같은 오류를 얻습니다. vector와 double은 다른 타입 객체니까 컴파일할 수 없다는 겁니다.
1
2
3
4
5
6
|
if (vector == (Vector)3.0){ // invalid operands to binary expression
//because Vector and double is different type object
cout << "It's same value" << endl;
}else{
cout << "Diff" << endl;
}
|
cs |
하지만 아래와 같이 형 변환을 명시적으로 해주게 되면 임시적으로 이항 연산 컨디션 내에서는 Vector객체로 생성자를 통해 생성되어 연산자 오버로드 멤버 함수와 비교되어 값이 출력되게 됩니다!
조금 어려울 수 있으나, 천천히 코드를 작성하고 읽어보시면 모두 이해가 될 내용이라고 생각됩니다!!
궁금한 점, 피드백, 문의 등은 아래 댓글창에 남겨주시면 감사하겠습니다!!
글 잘 보셨다면 공감과 궁금하신 분들께도 보여주시면 감사하겠습니다!!!
그럼 20000😜😜😜😜😜😜😜😜
'C++' 카테고리의 다른 글
[C++]C++의 제네릭, Template class에 대해서 (0) | 2021.02.17 |
---|---|
[C++] extern, volatile 제대로 알고 사용하기! (0) | 2020.12.21 |
[C++] static, const, explicit 제대로 알고 사용하기![1] (0) | 2020.12.18 |
C++로 구현하는 자료구조!!이중연결리스트(Doubly Linked List)@@ (1) | 2020.11.30 |
C++로 구현하는 자료구조!!!트리자료구조(Tree)@@ (1) | 2020.11.29 |
댓글