본문 바로가기

C++문법 공부

맴버 함수 사용시 const 키워드의 사용

객체 지향 프로그래밍에서 반드시 알아야 할 3가지 const의 사용법에 대해서 알아 보겠습니다.

맴버 함수에 const 가 사용되기 시작하면서 한번 정리하고 갈 필요성을 느꼈습니다.

 

첫번째, 함수 선언 맨 끝에 const를 붙이는 경우

대표적인 함수로 접근자로 쓰이는 Get 함수가 있습니다.

class Point
{
private:
	int x, y;
public:
	Point()
		:x(0), y(0){}
	Point(int argx, int argy)
	{
		x = argx;
		y = argy;
	}

	void SetX(int arg) 
	{
		x = arg;
	}
	void SetY(int arg)
	{
		y = arg;
	}

	int GetX() const
	{
		return x;
	}
	
	int GetY() const
	{
		return y;
	}
};

여기서 int GetX() constint GetY() const 는 const가 함수이름 맨 뒤에 붙어있습니다.

이렇게 쓰인 함수의 특징은 함수가 맴버변수의 값을 변경하지 않는다는 것입니다. 뿐만 아니라 컴파일러에게

"이 함수는 맴버 변수 변경 안할거야." 라고 이야기 하는 것과 같습니다.

컴파일러에게 이렇게 이야기 하는것이 왜 중요한지 아래 두번째 사례를 살펴 보겠습니다.

 

두번째, 매개변수로 const 타입을 받는 경우

(객체의 선언 단계에서 const가 붙는 경우)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
 
using namespace std;
 
class Point
{
private:
    int x, y;
public:
    Point()
        :x(0), y(0) {}
    Point(int argx, int argy)
    {
        x = argx;
        y = argy;
    }
 
    void Nothing()
    {
        cout << "나는 아무것도 아니다." << endl;
    }
 
    void SetX(int arg)
    {
        x = arg;
    }
    void SetY(int arg)
    {
        y = arg;
    }
 
    int GetX() const
    {
        return x;
    }
 
    int GetY() const
    {
        return y;
    }
 
    
};
 
void FuncPoint(const Point argPoint)
{
    int temp;
    temp = argPoint.GetX();    //성공
    argPoint.Nothing()    // 실패
}
cs

45행에 FuncPoint 라는 함수를 만들어 보았습니다. 

매개변수로 const Point 타입을 받습니다.

꼭 함수의 매개변수가 아니더라도 const 타입으로 생성된 객체는 위에서 설명한 첫번째 항목인

'맴버 함수 선언 맨 끝에 const를 붙이는 경우' 가 아니라면, 그를 제외한 모든 맴버 함수를 사용할 수가 없습니다.

18번 행을 보시면 Nothing 이라는 함수는 말 그대로 아무것도 아닌 녀석입니다. 맴버들이랑 아~무런 관계없는 출력문한줄만 덩그러니 있을 뿐이예요하지만 컴퓨터는 '맴버 함수 선언 맨 끝에 const를 붙이는 경우' 가 아니라면  그냥 다같은 분류로 취급합니다.함수 내용을 전~부 들여다 보고나서 아 이녀석은 맴버들을 수정하지 않는구나, 라고 판단하는건 코스트가 굉장히 큰 행동이죠? 그것보다는 이렇게 판단하는게 효율적입니다.

나는 '맴버 함수 선언 맨 끝에 const 붙인' 녀석만 맴버를 바꾸지 않는 녀석으로 간주한다. 나머지는 알빠노?

컴퓨터가 이렇게 판단하는거죠.

그래서 아무것도 아닌 녀석인 Nothing 함수도 49번행처럼 불러오게 되면 컴파일 에러가 발생하게 됩니다.

 

 

세번째, 반환형에서 const가 붙는 경우

(함수 선언 맨 앞에 const가 오는 경우)

세 가지 경우 중에 가장 사용 빈도가 낮아서 세번째로 붙였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyClass {
public:
    MyClass(int value) : m_value(value) {}
 
    const int& getValue() const { return m_value; }
 
private:
    int m_value;
};
 
int main() {
    MyClass obj(10);
    const int& value = obj.getValue();  // 가능
    value = 20;  // 컴파일 에러: const 참조는 수정할 수 없습니다.
    return 0;
}
 
cs

5번 행의 getValue 함수가 바로 반환형에 const가 붙은 예입니다.

 

세번째 경우는 반환형으로 가져온 값을 수정하지 못하게 하고 싶을 때 사용합니다.

 

예제부터 레퍼런스 타입을 사용한 것을 볼 수 있습니다.

레퍼런스 타입이 아닌 일반 타입을에 const 를 붙이는 경우는 거의 찾아볼 수 없습니다.

함수에 반환형이 있다는것은 뭘 의미하죠?

해당 값을 어딘가에 담아서 사용하겠다는 의미입니다. 지금 예제에서 13번행을 보시면 value 라는 변수에 값을 담았죠.

13번 행을 통해서 자연스럽게 value 가 m_value를 가리키는 레퍼런스가 됩니다. 이 레퍼런스가 const 타입이기 때문에

14번행이 에러가 발생하죠

 

레퍼런스 타입이 아닌 일반변수 타입의 반환형에 const를 붙이면 사실상 쓰는 의미가 없어집니다.

const int getValue() {
    return 10;
}

int main() {
    int num = getValue();  // 가능
    num = 20;  // 가능
    return 0;
}

num이라는 변수에 getValue()의 반환값을 담았습니다. 이는 const 타입이죠.

하지만 = 연산자가 작동하는 과정에서 값의 복사가 일어날 뿐이지 const 타입까지 복사되지는 않습니다.

int main() {
    const int NUM = 10;

    int num = NUM;  //값의 복사만 일어남
    num = 100;  //const 타입 까지 복사되지 않기 때문에 에러없이 실행 가능    
    
    return 0;
}

위 예제가 전부 에러 없이 실행 가능한 것과 같은 맥락입니다.

 

 

 

1. 함수 선언 맨 끝에 const를 붙이는 경우는 맴버의 수정을 불가능하게 만들 때 쓴다. 읽기 전용.
2. 매개변수로 const 타입을 사용할 때, const 로 선언된 객체는 1. 로 만든 맴버 함수만 불러 올 수 있다.
3. 반환형에 const를 붙이는 경우는 무조건 레퍼런스 타입과 함께 사용되며, 함수의 반환값을 수정하지 못하게 할 때 쓴다.

 

'C++문법 공부' 카테고리의 다른 글

2차원 배열과 포인터의 이해  (0) 2023.07.05
함수 템플릿  (0) 2023.07.03
소멸자의 virtual 선언  (0) 2023.06.30
가상함수 Virtual과 오버라이딩  (0) 2023.06.27
포함  (0) 2023.06.27