최신목록

2016년 1월 12일 화요일

[C++]const 변수와 함수, 클래스

const는 위치에 따라 의미가 달라져서 정리를 해본다.

1. const 변수

const int x = 5;
int const x = 5;

위 두개는 의미가 같으면 x자체의 값을 변경할 수 없다는 의미임. const는 자료형과의
위치는 상관이 없으며 포인터나 변수명과의 위치에 따라 의미가 달라진다.

int x = 5;
const int *y = &x;

int x = 5;
int const *y = &x;
x = 7; --> 에러아님
*y = 7; -->에러

위 두개는 의미가 같으며 *y에 대한 값을 변경할 수 없다는 의미임
*y는 x를 의미하나 x는 변경이 가능하고 *y는 변경이 불가능함
*y와 x가 같은 것을 의미하나 다른 값으로 혼동되어 변경되는것을 방지하기 위함이다.

int x= 5;
int* const y = &x;
x = 7;
*y = 7;
y = (int*)0x00000007; --> 에러

위의 의미는 y에 대한 값을 변경할 수 없다는 의미로 x의 값이 담겨있는 주소값을 의미하는 y가 변경되어 다른 주소를 가리키게 되는것을 방지하기 위함이다.

2. const 멤버 변수

위에서는 일반적인 const의 쓰임새를 얘기했다면 이제 집중적으로 클래스 내부에서 const가 어떻게 쓰이는지를 정리한다.

클래스 내에서 멤버 변수를 const로 선언을 하면 생성 시점에 초기화를 해야하며 그 이후에는 더 이상 값을 변경할 수 없게 된다.

class test
{
const int a;
public:
test(int a1):a(a1) {}
};

위처럼 변수 정의시 초기화시키는 클래스 initializer에서 const 멤버 변수에 대한 초기화가 이루어져야한다. 생성자의 바디안에서 초기화시 에러 발생한다.

3. const 함수

<const 매개변수>
void func(const int& param)
{
      param  = 7; --> 에러
}

참조에 의한 전달 방식일때 기존 caller에서 변수의 복사 오버헤드를 줄이기 위해 참조방식을 체택하였으나 변경을 원치 않을때에는 const를 붙여서 변경을 방지한다.

<const 멤버함수>
void func(int param) const
{
      a=1; //-->error
}
const 멤버함수는 클래스의 멤버함수에만 사용가능하다.
const로 지정된 멤버함수에서는 클래스의 멤버변수를 read only 권한으로만 사용가능하다는 의미이다.



위에서보면 const 객체인 t2는 const 멤버함수가 아닌 change 호출시 에러가 나는 것을 볼 수 있다. 이처럼 멤버 변수의 변경점이 없는 객체를 사용하고 싶을때 const 멤버함수를 구분하여 사용하였다면 구분해내기가 편할 것이다. 반면 const 멤버함수는 const 객체이든 비const 객체이든 호출에는 문제가 없다.

만약 멤버함수가 static으로 선언이 되었다면 클래스 객체와 무관하여 멤버의 변경이 불가능하므로 const선언이 의미가 없다. 하여 static 멤버 함수의 const 지정은 무의미하다.

하지만 const 멤버 함수도 예외적으로 멤버 변수의 변경을 허용할 수 있는 방법이 존재한다. 이것은 mutable 데이터 멤버이다. 아래와 같이 mutable로 선언시 const 멤버 함수에서 변경이 가능하게된다.

class test
{
  mutable int a;
public:
  test () {}
  void func1() const
  {
     a = 1;
  }
};

<const 리턴>
const 매개변수와 마찬가지로 참조를 리턴할 때 변경되는것을 방지하기 위해 사용된다.
매개변수일때와 마찬가지로 복사가 일어나기를 바라지 않아서 참조를 리턴하는데 참조를 리턴하였을 경우 아래와 같이 클래스의 멤버함수를 caller쪽에서 변경의 위험이 있다.


이를 방지하기 위해서 const로 보호를 한다.



4. const 클래스 객체

클래스 멤버 함수에 const를 걸면 그 함수 안에서는 멤버 변수의 변경이 불가하다고 하였다. 그렇다면 클래스 객체 자체에 const를 걸면 어떻게 될까? const 클래스 객체는 const 멤버 함수만 사용이 가능하게 된다. 일반 멤버 함수 사용시 컴파일 에러가 발생한다.

class test
{
  int c;
public:
  test () {}
  void func1() const
  {
     /*c = 1;*/   //-> 사용불가
  }
  void func2()
   {
     c = 2;
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  const test t1;
  t1.func1();
  t1.func2();  //--> error C2662: 'test::func2' : 'this' 포인터를 'const test'에서 'test &'(으)로 변환할 수 없습니다.
  return 0;
}



댓글 3개:

  1. 정리 잘 해두셨네요. 잘 보고 갑니다.

    답글삭제
  2. const가 헷갈려서 총 정리를 하려고 했는데 깔끔하고 쉽게 잘 정리해주셔서 감사합니다ㅠㅜㅜ 공부하는데 많은 도움이 되었습니다!!

    답글삭제