[061-] const와 관련해서 아직 못다한 이야기

김민성·2022년 7월 26일
post-thumbnail

const 객체와 const 객체의 특성들

다음과 같이 변수를 상수와 하듯이,

const int num = 0;

다음과 같이 객체도 상수화할 수 있다.

const SoSimple sim(20);

그리고 이렇게 객체에 const 선언이 붙게 되면, 이 객체를 대상으로는 const 멤버함수만 호출이 가능하다. 이는 객체의 const 선언이 다음의 의미를 갖기 때문이다.

"이 객체의 데이터 변경을 허용하지 않겠다!"

때문에 const 멤버함수의 호출만 허용하는 것이다. 물론 const로 선언되지 않은 함수 중에도 데이터를 변경하지 않는 함수가 있을 수 있다. 하지만 변경시킬 능력이 있는 함수는 아예 호출을 허용하지 않는 것이다. 그럼 예제를 통해 const 객체의 특성을 확인하자.

ConstObject.cpp

#include <iostream>
using namespace std;

class SoSimple
{
    private:
        int num;
    public:
        SoSimple(int n) : num(n)
        { }
        SoSimple& AddNum(int n)
        {
            num+=n;
            return *this;
        }
        void ShowData() const
        {
            cout<<"num: "<<num<<endl;
        }
};

int main(void)
{
    const SoSimple obj(7);
    // obj.AddNum(20);
    obj.ShowData();
    return 0;
}
num: 7

위의 예제에서 이 부분은,

const SoSimple obj(7);

const 객체를 생성하고 있고, 이 객체의 데이터 변경을 허용하지 않겠다는 의미이다.

// obj.AddNum(20);

위의 부분은 왜 에러가 나는 부분이냐면, const객체는 const 함수만 호출이 가능하기 때문이다.

obj.ShowData();

멤버함수 ShowData는 const 함수이기 때문에 const 객체를 대상으로 호출이 가능하다.

위 예제를 통해서 알 수 있듯이, 멤버변수에 저장된 값을 수정하지 않는 함수는 가급적 const로 선언해서, const 객체에서도 호출이 가능하도록 할 필요가 있다. 아주 간단한 예제이지만 const 선언이 많을수록 좋은 이유를 더불어 확인시켜준 예제이다.

const 함수 오버로딩

함수의 오버로딩이 성립하려면 매개변수의 수나 자료형이 달라야 한다. 하지만 다음과 같이 const 선언유무도 함수 오버로딩의 조건에 해당이 된다.

void SimpleFunc() { . . . . }
void SimpleFunc() const { . . . . }

위의 두 함수가 어떠한 경우에 호출되는지 예제를 통해 알아보자.

ConstOverloading.cpp

#include <iostream>
using namespace std;

class SoSimple
{
    private:
        int num;
    public:
        SoSimple(int n) : num(n)
        { }
        SoSimple& AddNum(int n)
        {
            num+=n;
            return *this;
        }
        void SimpleFunc()
        {
            cout<<"SimpleFunc: "<<num<<endl;
        }
        void SimpleFunc() const
        {
            cout<<"const SimpleFunc: "<<num<<endl;
        }
};

void YourFunc(const SoSimple &obj)
{
    obj.SimpleFunc();
}

int main(void)
{
    SoSimple obj1(2);
    const SoSimple obj2(7);

    obj1.SimpleFunc();
    obj2.SimpleFunc();

    YourFunc(obj1);
    YourFunc(obj2);
    return 0;
}
SimpleFunc: 2
const SimpleFunc: 7
const SimpleFunc: 2
const SimpleFunc: 7

위의 예제를 살펴보자면,

void SimpleFunc()
{
    cout<<"SimpleFunc: "<<num<<endl;
}
void SimpleFunc() const
{
    cout<<"const SimpleFunc: "<<num<<endl;
}

함수의 const 선언 유무는 함수 오버로딩의 조건이 된다.

void YourFunc(const SoSimple &obj)
{
    obj.SimpleFunc();
}

참조자를 인자로 받기 때문에 obj1도, obj2도 인자가 될 수 있다.
다만, 여기선 const로 선언되었기 때문에 참조자 obj(&obj)를 통해가지고는 객체를 변경시킬 수 없는 것 뿐이다.

"const 참조자니까 const 객체만 전달받는다" 라는 엉뚱한 생각하지 말자.

const SoSimple obj2(7);

obj2.SimpleFunc();

const 객체 또는 참조자를 대상으로 멤버함수 호출 시 const 선언된 멤버함수가 호출된다!

profile
다양한 활동을 통해 인사이트를 얻는 것을 즐깁니다. 저 또한 인사이트를 주는 사람이 되고자 합니다.

0개의 댓글