[디딤돌 C++] 46. 전역 연산자 중복 정의

개발자는 전역이나 클래스 내에서 연산자 중복 정의할 수 있습니다. 먼저 전역에서 연산자 중복 정의 방법을 알아봅시다.

연산자 중복 정의할 때는 메서드 이름 대신 operator 키워드 뒤에 정의할 연산 기호를 명시합니다. 그리고 피연산자는 순서대로 입력 매개 변수 리스트에 열거하고 연산 결과는 리턴 형식으로 표현합니다.

[리턴 형식] operator [연산기호] (입력 매개 변수 리스트)

{

[기능 구현]

}

간단하게 학생 클래스를 정의한 후에 == 연산자를 전역에 중복 정의해 볼게요. 다음과 같은 학생 클래스가 있다고 가정해요.

//Student.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Student
{
    string name;
    const int num;
public:
    Student(int num,string name);
    bool IsEqual(int num)const;
    void View()const;
};
//Student.cpp
#include "Student.h"
Student::Student(int num,string name):num(num)
{
    this->name = name;
}
bool Student::IsEqual(int num)const
{
    return this->num == num;
}
void Student::View()const
{
    cout<<"번호:"<<num<<" 이름:"<<name<<endl;
}

이와 같은 학생 클래스가 있다면 사용하는 코드에서는 학생과 번호를 비교할 때 IsEqual 메서드를 사용할 수 있겠죠.

//연산자 중복 정의하기 전
#include "Student.h"

int main()
{
    Student stu(3,"홍길동");
    int num;
    cout<<"번호:";
    cin>>num;
    if(stu.IsEqual(num))
    {
        cout<<"학생 번호는 "<<num<<"입니다."<<endl;
    }
    else
    {
        cout<<"학생 번호는 "<<num<<"이 아닙니다."<<endl;
    }
    stu.View();
    return 0;
}

이제 학생과 번호를 비교할 때 IsEqual 메서드 대신 == 연산자를 사용할 수 있게 전역에 == 연산자를 중복 정의합시다. 연산자를 중복 정의하는 곳은 제공하는 개발자의 몫이므로 Student.h 파일에 선언문을 작성하고 Student.cpp 파일에 정의문을 작성합니다.

//Student.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Student
{
    string name;
    const int num;
public:
    Student(int num,string name);
    bool IsEqual(int num)const;
    void View()const;
};

bool operator == (const Student &stu, int num);
//Student.cpp
#include "Student.h"
Student::Student(int num,string name):num(num)
{
    this->name = name;
}
bool Student::IsEqual(int num)const
{
    return this->num == num;
}
void Student::View()const
{
    cout<<"번호:"<<num<<" 이름:"<<name<<endl;
}
bool operator == (const Student &stu, int num)
{
    return stu.IsEqual(num);
}

이처럼 정의하면 사용하는 곳에서 IsEqual 메서드 대신 == 연산 기호를 사용할 수 있습니다.

//연산자 중복 정의 예1
#include "Student.h"

int main()
{
    Student stu(3,"홍길동");
    int num;
    cout<<"번호:";
    cin>>num;
    if(stu==num) //연산 기호 ==를 사용
    {
        cout<<"학생 번호는 "<<num<<"입니다."<<endl;
    }
    else
    {
        cout<<"학생 번호는 "<<num<<"이 아닙니다."<<endl;
    }
    stu.View();
    return 0;
}

그런데 이처럼 정의하면 stu==num 과 같은 표현은 문법에 맞는 표현이지만 num == stu는 문법에 맞지 않는 표현입니다. 사용하는 개발자는 == 연산자는 교환 법칙이 성립할 것이라고 생각하여 num == stu 구문을 사용하면 문법적 오류가 발생합니다. 제공하는 개발자는 이러한 문법적 오류가 발생하지 않게 사용하는 개발자의 관점에서 편의성을 제공해야 합니다.

//Student.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Student
{
    string name;
    const int num;
public:
    Student(int num,string name);
    bool IsEqual(int num)const;
    void View()const;
};

bool operator == (const Student &stu, int num);
bool operator == (int num, const Student &stu);
//Student.cpp
#include "Student.h"
Student::Student(int num,string name):num(num)
{
    this->name = name;
}
bool Student::IsEqual(int num)const
{
    return this->num == num;
}
void Student::View()const
{
    cout<<"번호:"<<num<<" 이름:"<<name<<endl;
}
bool operator == (const Student &stu, int num)
{
    return stu.IsEqual(num);
}
bool operator == (int num, const Student &stu)
{
    return stu.IsEqual(num);
}
//연산자 중복 정의 예2
#include "Student.h"
int main()
{
    Student stu(3,"홍길동");
    int num;
    cout<<"번호:";
    cin>>num;
    if(stu == num) //연산 기호 ==를 사용
    {
        cout<<"학생 번호는 "<<num<<"입니다."<<endl;
    }
    else
    {
        cout<<"학생 번호는 "<<num<<"이 아닙니다."<<endl;
    }
    if(num == stu) //연산 기호 ==를 사용
    {
        cout<<"학생 번호는 "<<num<<"입니다."<<endl;
    }
    else
    {
        cout<<"학생 번호는 "<<num<<"이 아닙니다."<<endl;
    }
    stu.View();
    return 0;
}

이처럼 연산자 중복 정의할 때는 사용하는 개발자의 편의성을 높이기 위한 것이므로 제공하는 개발자는 신중하게 검토하여 정의해야 합니다. 그리고 포인터 형식은 사용자 정의 형식이 아니기 때문에 동적으로 개체를 생성하여 프로그래밍할 때 사용자는 연산자 중복 정의를 사용하는 것이 불편할 수도 있습니다. 따라서 IsEqual 메서드처럼 사용자가 연산자를 대신하여 사용할 수 있는 메서드도 함께 제공하세요.

형식 변환 오류