const 메소드와 const 객체와 const 포인터

const 키워드를 사용해서 변수를 심볼릭 상수(symbolic constant)로 변형할 수 있다는 것은 이미 배운바 있습니다.

 

또한 const를 포인터에 사용하는 방법이 두가지 있었습니다.

 

▶ 포인터 변수에 const 를 사용하면 포인터 변수를 변경할 수 없습니다. (포인터의 상수화)

 

포인터의 간접 참조연산자(indirection operator)에 const 를 사용하면 포인터가 가리키는 변수의 값을 변경할 수 없습니다. (간접 참조연산자를 사용할 수 없다)

const 메소드

* const 메소드는 무엇인가요?

 

아래의 코드에서 const 는 () 다음과  { 중괄호 시작 사이에 위치합니다. 이렇게 const 를 걸어놓으면 클래스의 멤버변수의 변경을 하지 못합니다. 주석처리한 부분은 멤버변수를 변경하는 코드인데 const 메소드에서는 사용할 수 없습니다.

 

 

* const 메소드를 왜 사용하나요?

 

const 한정자를 사용해서 메소드에서 멤버변수의 값을 변경할 수 없도록 바꾸면 디버깅 할 때 추적이 수월합니다. const 메소드에서 멤버 변수를 변경하지 않았다는 사실을 알 수 있기 때문이죠. 물론 멤버변수를 변경할 필요가 없는 경우에 사용합니다. 위의 메소드는 단순한 getter 입니다. private 에 있는 멤버의 값을 리턴하는 것이 주요 기능이기 때문에 const 를 사용해도 됩니다. 

 

이름을 getter 로 지었다고 하더라도 멤버 변수를 변경할 가능성은 항상 있습니다. 유지보수가 잘되는 코드를 만들기 위해서 const 를 붙이는 것은 좋은 습관입니다.

 

const 객체와 const 포인터

const 객체와 const 포인터에 대하여 알아볼 시간입니다.

 

 MyPosition 클래스로 테스트를 해봅니다. 아래의 클래스를 new 키워드로 생성하여 const 한정자를 적용시킵니다.

 

▶ const 객체에 포인터를 선언하면 const 메소드만 호출할 수 있습니다. 

 

▶ 객체에 const 포인터를 선언하면 다른 객체를 가리킬 수 없습니다.

 

const 객체 포인터 등의 용어 때문에 헷갈리기 쉽습니다.

 

생성자와 소멸자

 

아래와 같이 세개의 객체를 힙 메모리에 생성합니다. const 가 붙어있는 위치에 주목할 필요가 있습니다.

 

 첫번째 객체 ptrPos는 제한이 없습니다.

 

 두번째 객체 ptrConstPos 는  const 객체에 포인터를 선언합니다. const 메소드만 사용가능합니다.

 

 세번째 객체 prtConstPtr 은 객체에 const 포인터를 선언합니다. 다른 객체를 가리킬 수 없습니다.

 

* 결과를 확인할 수 있는 출력코드를 넣어 둡니다.

 

 

아래 코드를 보면 첫번째 객체에는 아무 제한이 없이 setter를 사용해서 멤버값을 변경합니다.

 

둘째 객체는 const가 아닌 setter 로 멤버변수를 변경할 수 없습니다. const인 getter 를 호출할 수는 있습니다.

 

세번째 객체는 const 포인터 즉 포인터가 상수입니다. 다른 객체로 바꿀 수 없죠.

 

결과창

위와 같은 결과를 확인할 수 있습니다.

 

정리

const 라는 한정자를 그냥 상수를 만들기 위해 사용할 때는 몰랐는데 이렇게 사용해 보면 멀쩡히 있던 객체가 한층 복잡해지는 것이 보입니다. 여기까지도 충분히 복잡하지만 const 의 사용법은 이것이 다는 아닙니다. 다들 어려워 하는 부분이기 때문에 처음에 이해가 안되도 너무 걱정할 필요는 없습니다.

 

교재나 온라인의 설명들을 좀 더 읽어 보고 직접 연습을 해보는 방법이 좋습니다.

 

* 예제 코드

#include <iostream>

using namespace std;

#define Line cout <<"\n-----------------------------\n"

class MyPosition {
public:
	MyPosition();
	~MyPosition();
	void setXPos(int x) { this->xPos = x; }
	int getXPos() const {
		// const 한정자는 멤버변수의 값을 변경할 수 없다.
		// this->xPos = 19;
		return this->xPos;
	}	
	void setYPos(int y) { this->yPos = y; }
	int getYPos() const { return this->yPos; }

private:
	int xPos;
	int yPos;
};

MyPosition::MyPosition()
{
	xPos = 0;
	yPos = 0;
}
MyPosition::~MyPosition()
{}

int main()
{

	MyPosition* ptrPos = new MyPosition;
	const MyPosition* ptrConstPos = new MyPosition;
	MyPosition* const ptrConstPtr = new MyPosition;
	
	Line;
	cout << " ptrPos x : " << ptrPos->getXPos() << endl;
	cout << " ptrPos y : " << ptrPos->getYPos() << endl;

	cout << " ptrConstPos x : " << ptrConstPos->getXPos() << endl;
	cout << " ptrConstPos y : " << ptrConstPos->getYPos() << endl;
		
	cout << " ptrConstPtr x : " << ptrConstPtr->getXPos() << endl;
	cout << " ptrConstPtr y : " << ptrConstPtr->getYPos() << endl;


	ptrPos->setXPos(17);
	ptrPos->setYPos(22);

	// const 메소드에만 접근할 수 있다.
	// ptrConstPos->setXPos(23);
	// ptrConstPos->setYPos(99);

	// 포인터 변수를 변경하는 것은 가능
	ptrConstPos = ptrPos;

	ptrConstPtr->setXPos(35);
	ptrConstPtr->setYPos(42);

	// 상수 포인터 가리키는 주소는 고정
	// ptrConstPtr = ptrPos;

	Line;
	cout << " ptrPos x : " << ptrPos->getXPos() << endl;
	cout << " ptrPos y : " << ptrPos->getYPos() << endl;

	cout << " ptrConstPos x : " << ptrConstPos->getXPos() << endl;
	cout << " ptrConstPos y : " << ptrConstPos->getYPos() << endl;

	cout << " ptrConstPtr x : " << ptrConstPtr->getXPos() << endl;
	cout << " ptrConstPtr y : " << ptrConstPtr->getYPos() << endl;

	return 0;
}

공유하기

facebook twitter kakaoTalk kakaostory naver band