const 키워드에 대한 이해(c++)

const의 기본적 내용은 아래 글을 참조하시기 바랍니다.












2014/01/14 - [프로그래밍/C언어] - 상수포인터, 포인터상수, const


c언어에서의 const를 확장하여 c++의 클래스 내부에서 사용되어지는 예를 살펴보겠습니다.



예1) 멤버변수를 const로 선언한 경우


위 코드를 컴파일해보면 두 개의 에러가 생긴다.


첫 번째는 초기화 되지 않은 멤버 Mango::m라고 하고, 두 번째는 Mango::m의 값이 읽기전용이기 때문에 값을 넣을 수 없다는 에러다.

초기화를 시켜야 하지만 생성자에서 초기화를 할 수 없다고 유추해 볼 수 있다.


const멤버의 초기화


이 방법은 멤버 이니셜 라이져를 이용한 전통적인 방법이다.


c++11에서는 다음과 같은 방법도 제공한다. 다음 방법은 c++11에서만 가능한 방법이므로 주의하도록 한다.


이 방법의 특징은 생성되는 모든 객체에 대해서 m 값이 모두 10으로 초기화가 된다. 이런 경우 m의 값을 static으로 선언하는 것이 합당할 것이다. 



예2) 복사 생성자의 인수로 const의 사용

클래스 내부의 복사생성자의 인수는 const로 선언된다.



코드 12줄 복사생성자의 인수로 const를 사용했다. 물론 const를 지우고 컴파일해도 에러는 없다. 복사생성자의 경우 인수에 const를 사용할 것을 권장한다. 문법적 의미를 살펴보면 const 수식으로 전달받은 test객체에 대한 조작(수정,변환)을 하지 않겠다는 의미다. 


왜 const의 사용을 권장해야하나?

복사생성자의 목적은 기존에 있던 객체의 데이터를 다른 객체에 그대로 복사하기 위함이다. 이 과정에서 기존 객체의 데이터 조작은 없어야 할 것이다. 코드적으로 완벽하다면 그럴 일이 없겠지만, 굳이 이러한(const) 안정장치를 사용하는 이유는 경험적인 이유일 것이라 생각된다.  인위적으로 복사할 객체의 내부데이터를 변화시켜보자.



바로 에러를 내는군요. const는 일종의 안전장치다. 함수의 목적이 데이터의 변경이 필요 없을 경우 const의 사용은 프로그램을 더욱 명확하게 해준다.


예3) 멤버변수를 조작하지 않는 멤버함수의 사용.

const를 멤버 함수에 사용하게 되면 함수에 기능적인 제한을 준다. 멤버 함수는 멤버 변수에 접근할 수 있는데, const로 제한을 두면 접근은 하되 멤버변수를 변화시키는 행위를 허용하지 않는다.


에러가 나는 경우


1. 직접적인 멤버데이타의 변화.


멤버변수의 변경을 시도했다.


에러메세지를 보면  m이 const로 선언되지 않았음에도 const로 인식하고 있다. const 멤버함수 내부에서는 일시적으로 멤버변수를 const로 인식하는 것임을 알 수 있다.

 

2. 간접적인 멤버데이타의 변화 가능성

transData 함수 내부에서 멤버변수의 변경을 하지도 않았고, 내부에서 호출한 getData() 도 멤버 변수를 변경하지 않았다.


그럼에도 위와같은 에러가 난다. getData()라는 함수는 멤버변수를 변경할 가능성이 있기 때문이다. 실제로 멤버변수를 변경하지 않았지만, 컴파일러는 그 부분을 체크하지 않는다. 컴파일러가 체크하는 부분은 const의 유무, 즉 멤버변수를 변경할 가능성이 있는지 없는지다. 그 가능성의 유무는 const 키워드로 알 수 있다.


3. 포인터값의 리턴

포인터 값의 리턴 또한 간접적인 데이터 조작의 가능성이라는 측면에서 생각해볼 수 있다. 포인터 값을 넘겨주면 포인터의 역참조를 통해 그 값을 변경할 수 있다. const멤버 함수 내부에서 멤버변수의 포인터를 리턴하는 경우를 생각해 보면, 이는 멤버 변수의 변경의 기회를 제공하게 된다.


다음 에러 메세지를 잘 분석해보자.


리턴되는 m의 값을 상수지시포인터(const int*)로 취급하고 있다. 함수 선언에 리턴되는 값도 상수지시포인터로 const를 붙이면 위 에러는 해결된다. 다시말해 리턴값을 상수지시 포인터로 선언하여 멤버 변수의 변경의 기회를 주지 않으면 위 에러는 해결된다.



예4) const를 이용한 오버로딩

이 부분은 꽤 흥미로웠다. 비록 사용을 많이 할지 모르겠지만 말이다.




2014/04/17 - [프로그래밍/c++] - 오버로딩 오버라이딩 (overloading overriding) c++


멤버함수 transData(), getData()는 각각 오버로딩되어있다. tansData의 경우는 각각 인수의 개수가 틀리고 const가 하나는 있고 하나는 없다. getData()는 const의 유무에 따라 오버로딩 되어있다.

다음은 실행화면이다.


오버로딩 조건에 따라서 그에 맞는 transData()함수가 호출되었고 각각의 transtData()함수는 const의 유무에 따라 그에 맞는 getData()함수를 호출하였다.


물론 transData() 함수도 동일한 인수로 const의 유무만으로 오버로딩할 수 있다.


물론 이경우 생성된 객체가 const 냐 아니냐에 따라서 함수를 택하게 된다. const 객체는 멤버함수를 변경하면 안되기 때문에 const 멤버 함수만 호출할 수 있다.


Tags
이 댓글을 비밀 댓글로