Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C++] 임시객체로의 자동 형 변환과 형 변환 연산자(Conversion Operator) 본문

Programming/C++

[Programming/C++] 임시객체로의 자동 형 변환과 형 변환 연산자(Conversion Operator)

scii 2021. 2. 5. 22:57

C++에서는 객체간의 대입연산을 허용한다. 당연하게도 두 객체의 자료형이 일치할 때에만 대입연산이 가능하다.

#include <iostream>

#pragma warning(disable: 4996)

using std::cout;
using std::cin;
using std::endl;


class Number {
private:
    int num;

public:
    Number(int n = 0) : num(n) {
        cout << "Number(int n=0)" << endl;
    }

    Number& operator=(const Number& ref) {
        cout << "operator=()" << endl;
        num = ref.num;
        return *this;
    }

    void ShowNumber() const {
        cout << num << endl;
    }
};


 int main(const int argc, const char* const argv[]) { 
     Number num;
     num = 30;
     num.ShowNumber();

     return 0;
}

/* 결과

Number(int n=0)
Number(int n=0)
operator=()
30

*/

출력 결과를 통해 알 수 있는 것은 다음과 같다.

// 1단계. 임시객체의 생성
num = Number(30);

// 2단계. 임시객체를 대상으로 하는 대입 연산자의 호출
num.operator=(Number(30));

여기서의 핵심은 임시객체의 생성이다. 그리고 이러한 임시객체의 생성을 통해 대입연산이 진행되는데에는 다음과 같은 문법적 기준이 존재한다.

A형 객체가 와야 할 위치에 B형 데이터(또는 객체)가 왔을 경우, B형 데이터를 인자로 전달받는 A형 클래스의 생성자 호출을 통해서 A형 임시객체를 생성한다.

따라서 위의 예제에서는 'Number형 객체가 와야 할 위치에 int형 데이터가 와서, int형 데이터를 인자로 전달받는 Number 클래스의 생성자 호출을 통해 Number형 임시객체를 생성한 것' 이다. 그리고나서 두 Number객체를 대상으로 대입연산을 진행한다.

이렇듯, 기본자료형 데이터를 객체로 형 변환하는 것은 적절한 생성자의 정의를 통해 얼마든지 가능하다. 그렇다면 반대로 객체를 기본 자료형 데이터로 형 변환하는 것도 가능할까? 

가능하다. 예를 들어 앞서 정의한 Number 클래스를 대상으로 다음과 같은 덧셈연신이 가능 하려면,

int main(void) {
  Number num1;
  num1 = 30;
  Number num2 = num1 + 20;
  num2.ShowNumber();
  
  return 0;
}

Number 클래스가 + 연산자를 오버로딩하고 있거나, num1이 int형 데이터로 변환이 되어야 한다.

#include <iostream>

#pragma warning(disable: 4996)

using std::cout;
using std::cin;
using std::endl;


class Number {
private:
    int num;

public:
    Number(int n = 0) : num(n) {
        cout << "Number(int n=0)" << endl;
    }

    Number& operator=(const Number& ref) {
        cout << "operator=()" << endl;
        num = ref.num;
        return *this;
    }

    // 형 변환 연산자의 오버로딩
    operator int() {
        return num;
    }

    void ShowNumber() const {
        cout << num << endl;
    }
};


 int main(const int argc, const char* const argv[]) { 
     Number num1;
     num1 = 30;
     
     Number num2 = num1 + 20;

     num2.ShowNumber();

     return 0;
}

/* 결과

Number(int n=0)
Number(int n=0)
operator=()
Number(int n=0)
50

*/

위의 예제에서 정의한 형 변환 연산자는 다음과 같다.

operator int() {
  return num;
}

이렇듯 형 변환 연산자는 반환형을 명시하지 않는다. 하지만 return문에 의한 값의 반환은 얼마든지 가능하다. 그리고 오버로딩 된 연산자의 이름이 operator+ 이면, + 연산자가 등장했을 때 호출되는 것과 유사하게 operator int는 다음의 의미로 이해하면 된다.

int형으로 형 변환해야 하는 상황에서 호출되는 함수이다.

즉, int형으로 형 변환되어야 하는 상황에서 호출이 되며, 이 때 return문에 의해 반환되는 값이 int형으로의 형 변환 결과가 되는 것이다. 그래서 다음 문장의 실행과정에서

Number num2 = num1 + 20;

num1 객체의 operator int 함수가 호출되어, 이 때 반환되는 값 30과 20의 덧셈연산이 진행되며, 이 연산의 결과로 num2 객체가 생성된 것이다. 

Comments