멤버 함수에 붙는 const 키워드의 역할은 해당 멤버 함수가 상수 객체 대해 호출될 함수라는 사실을 의미한다.
이러한 함수는 먼저 클래스의 인터페이스를 이해하기 좋게하기 위해 사용되며, 두 번째로 이 키워드를 통해 상수 객체를 사용할 수 있게 하기위함이다.
cosnt 키워드가 있고 없고의 차이만 있는 멤버 함수들은 오버로딩이 가능하다. 오버로드를해서 각 버전마다 반환 타입을 다르게 가져간다면 상수 객체와 비상수 객체의 쓰임새를 다르게 가져갈 수 있다.
class TextBlock {
public:
const char& operator[](std::size_t position) const
{ return text[position]; }
char& operator (std::size_t poisition)
{ return atext[position]; }
private:
std::string text;
}
다만 이런식의 오버로딩을 진행하면 내부적인 코드중복을 피할 수 없다. (const 성격에 대한 처리를 제외하고는 결국 같은 내용의 코드가 진행되기 때문이다.) 이러한 코드중복을 피하기 위해서는 두번의 캐스팅을 통해서 cosnt 껍데기를 날릴 수 있다. 실제로 const 성질을 날려보내는것은 아니고, 내부적으로 비상수 버전에서 상수버전을 호출하게 만드는 형식이다. 구현방식은 다음과 같다.
class TextBlock {
public:
const char& operator[] (std::size_t position) const
{
//...
return text[position];
}
char& operator[] =(std::size_t position)
{
return const_cast<char&>(
static_cast<const TextBlock&>(*this)[position]);
}
//....
}
1) [] 연산자의 상수버전을 호출한다.
2) *this의 타입에 const를 붙인다.
3) const 캐스팅을 통해 []연산자의 리턴타입에 const cast를 통해 const 속성을 제거한다.
*this의 타입 캐스팅을 통해 상수 operator를 호출한다는 점이 중요한 부분이다. 이 역순으로 상수멤버함수에서 비상수버전을 호출하게되면 컴파일러와의 내규가 깨지게되므로 위의 방식과 반대로 구현해선 안된다.
+) const를 붙인 선언은 컴파일러가 사용상의 에러를 잡아내는데 큰 도움을 주므로 멤버함수에서의 사용도 적극적으로 하자
+)컴파일러에서 비트수준의 상수성을 지켜주지만, 코딩과정에선 개념적인 상수성을 지켜주어야한다.
+) 상수 멤버 및 비상수 멤버 함수가 기능적으로 똑같이 구현되어있을 경우 중복을 피하기 위해, 비상수 버전이 상수 버전을 호출하게 만들자
reference
- Effective C++
'Language > C++' 카테고리의 다른 글
Variant 초기화의 중요성 bad_variant_access (0) | 2022.06.03 |
---|---|
참조 전달 문법 std::move, std::forward (0) | 2022.01.13 |
이동생성자와 보편참조법(universal ref) (0) | 2022.01.07 |
enable_shared_from_this의 사용법 (0) | 2022.01.04 |
lvalue와 rvalue + 우측값 참조법 (0) | 2021.12.21 |