링크를 참고하여 다시 아래의 코드를 보자.
여기서 printValue는 value1, value2를 출력만 할 뿐, 수정은 하지 않는다.
#include <stdio.h>
#include <iostream>
using namespace std;
class TEST
{
public:
int value1;
int value2;
TEST()
{
cout << "생성자 호출" << endl;
value1 = 1;
value2 = 2;
}
void printValue()
{
cout << value1 << ", " << value2 << endl;
}
};
int main(void)
{
TEST test;
test.printValue();
return 0;
}
이런 경우, const 키워드를 이용하여 상수형 메서드로 만들 수 있다.
상수형 메서드는 멤버 변수를 수정할 수 없고, 상수형 메서드에서 다른 메서드가 변수를 바꾸지도 못하게 한다.
class TEST
{
public:
...
void printValue() const
{
value1 = 10; //compile error
cout << value1 << ", " << value2 << endl;
}
};
따라서 아래의 코드도 compile error가 발생한다.
void setValue1(int val)
{
value1 = val;
}
void printValue() const
{
setValue1(5); //complie error
cout << value1 << ", " << value2 << endl;
}
mutable을 이용하면 상수형 메서드에서 예외로 값을 수정할 수 있다.
class TEST
{
public:
mutable int value1;
...
void setValue1(int val)
{
value1 = val;
}
void printValue() const
{
//setValue1(5); //compile error
value1 = 5;
cout << value1 << ", " << value2 << endl;
}
};
그러나 여전히 setValue1은 사용하지 못하는데, mutable은 상수형 메서드에서 예외를 허용하기 때문이다.
따라서 setValue1에 const 키워드를 추가하면 된다.
#include <stdio.h>
#include <iostream>
using namespace std;
class TEST
{
public:
mutable int value1;
int value2;
TEST()
: value1(1), value2(2)
{
cout << "생성자 호출" << endl;
}
TEST(int val1, int val2)
{
value1 = val1;
value2 = val2;
cout << "생성자 호출 2" << endl;
}
void setValue1(int val) const
{
value1 = val;
}
void printValue() const
{
setValue1(5);
//value1 = 5;
cout << value1 << ", " << value2 << endl;
}
};
int main(void)
{
TEST test = TEST(3, 4);
test.printValue();
return 0;
}
하지만 당연히 멤버 변수 수정을 하지 않기 위해 const를 사용하였으므로 mutable 사용은 자제하는 것이 좋다.
const_cast<>
const_cast는 상수형 포인터에서 const를 일시적으로 제거할 수 있다.
이것은 mutable이 아닌 변수에 대해서도 가능하다.
위의 코드에서 setValue1을 아래와 같이 고쳐보자.
class TEST
{
public:
mutable int value1;
int value2;
...
void setValue1(int val) const
{
value1 = val;
value2 = val; //compile error
}
};
setValue1 메서드가 const로 선언되었으나, value1은 mutable이므로 변환가능하다.
하지만 value2를 변형하려고 하니 compile error가 발생하게 된다.
아래와 같이 임시로 newValue2를 선언한 후, value2를 const_cast로 type 캐스팅하면
const의 제한을 임시로 해제할 수 있다.
void setValue1(int val) const
{
value1 = val;
//value2 = val; //compile error
int& newValue2 = const_cast<int&>(value2);
newValue2 = val;
}
main에서 printValue를 호출하여 setValue1이 호출되었고, value2도 변경된 것을 알 수 있다.
최종 코드는 아래와 같다.
#include <stdio.h>
#include <iostream>
using namespace std;
class TEST
{
public:
mutable int value1;
int value2;
TEST()
: value1(1), value2(2)
{
cout << "생성자 호출" << endl;
}
TEST(int val1, int val2)
{
value1 = val1;
value2 = val2;
cout << "생성자 호출 2" << endl;
}
void setValue1(int val) const
{
value1 = val;
//value2 = val; //compile error
int& newValue2 = const_cast<int&>(value2);
newValue2 = val;
}
void printValue() const
{
setValue1(5);
//value1 = 5;
cout << value1 << ", " << value2 << endl;
}
};
int main(void)
{
TEST test = TEST(3, 4);
test.printValue();
return 0;
}
const_cast는 const로 선언된 포인터만 해제할 수 있다.
일반 변수의 const와 함수 포인터, 멤버 함수에 대한 const는 해제할 수 없다.
아래의 value는 여전히 100임을 알 수 있다.
#include <stdio.h>
#include <iostream>
using namespace std;
int main(void)
{
const int value = 100;
// value = 101; compile error
int& newValue = const_cast<int&>(value);
newValue = 500;
printf("%d\n", value); // 100; 해제 불가능
return 0;
}
'개발 > C, C++' 카테고리의 다른 글
C++ - 복사 생성자를 이용한 객체의 깊은 복사 (Deep Copy using Copy Constructor) (0) | 2021.08.10 |
---|---|
C++ - 명시적 디폴트 생성자 (0) | 2021.07.29 |
C++ - 생성자 초기화 리스트 (Constructor Member Initializer List) (0) | 2021.07.26 |
C 언어에서 날짜 구하기 (2) | 2021.07.24 |
C++ - 함수 템플릿 (Function Template) (0) | 2021.07.22 |
댓글