본문 바로가기
프로그래밍 언어/C++

[C++] 연산자 재정의 (Operator Overloading)

by 까망 하르방 2025. 3. 5.
반응형

연산자 재정의 (Operator Overloading)

사용자 정의 타입에서 +, - 등 연산자 사용할 수 있는 문법

class Point
{
	int x = 0;
	int y = 0;
public:
	Point() = default;
	Point(int x, int y) : x{ x }, y{ y } {}
};

int main()
{
	Point p1{ 1, 1 };
	Point p2{ 2, 2 };

	Point p3 = p1 + p2;	// ?? -> error
}


「 a + b 」
→ a, b 중 「operator+」 라는 함수 호출
 찾을 수 없는 경우 Error


→ 「 operator+(a, b) 」 or 「 a.operator+(b) 」
 「 operator+(a, b) 」 함수 인자 2개로 멤버가 아닌 함수로 구현
 「 a.operator+(b) 」 함수 인자 1개로 멤버 함수로 구현


멤버가 아닌 함수

• 멤버가 아닌 멤버 데이터에 접근하려면 public 영역에 선언
• getter 멤버 함수 제공
• operator+를 friend 함수로 등록

class Point
{
	int x{ 0 };
	int y{ 0 };
public:
	Point() = default;
	Point(int x, int y) : x{ x }, y{ y } {}

	friend Point operator+(const Point& p1, const Point& p2);
};

Point operator+(const Point& p1, const Point& p2)
{
	Point pt{ p1.x + p2.x, p1.y + p2.y };
	return pt;
}

int main()
{
	Point p1{ 1, 1 };
	Point p2{ 2, 2 };

	Point p3 = p1 + p2;	// operator+(p1, p2)
}

 

 

멤버 함수로 구현하는 경우

• 「 + 」 연산자는 이항 연산자 이지만 operator+ 멤버 함수의 인자는 1개
• 상수 객체도 덧셈을 할 수 있어야 하므로 const member function 구현

class Point
{
	int x{0};
	int y{0};
public:
	Point() = default;
	Point(int x, int y) : x{x}, y{y} {}

	Point operator+(const Point& p) const
	{
		Point pt{p.x + x, p.y + y};
		return pt;
	}
};

int main()
{
	const Point p1{1, 1};
	Point p2{2, 2};

	Point p3 = p1 + p2;	// p1.operator+(p2)
}

Q) 멤버 함수, 멤버 아닌 함수 모두 제공한다면?

멤버 함수와 멤버가 아닌 함수를 모두 제공하면
컴파일 에러 발생
반드시 둘 중 한 개만 제공해야 한다. 

// 멤버 함수와 멤버가 아닌 함수를 모두 제공하는 경우
class Point
{
	int x{0};
	int y{0};
public:
	Point() = default;
	Point(int x, int y) : x{x}, y{y} {}

	Point operator+(const Point& p) const
	{
		Point pt{p.x + x, p.y + y};
		return pt;
	}
	friend Point operator+(const Point& p1, const Point& p2);
};
Point operator+(const Point& p1, const Point& p2)
{
	Point pt{p1.x + p2.x, p1.y + p2.y};
	return pt;
}
int main()
{
	Point p1{1, 1};
	Point p2{2, 2};

	Point p3 = p1 + p2;	
}



Q) 멤버 함수 vs 멤버가 아닌 함수

private 멤버 접근하기에는 멤버 함수가 좋지만.
하지만 첫번째 인자가 사용자 정의 타입이 아닌 경우
멤버 함수로 만들 수 없는 경우가 있다.

class Point
{
	int x{ 0 };
	int y{ 0 };
public:
	Point() = default;
	Point(int x, int y) : x{ x }, y{ y } {}

	Point operator+(const Point& p) const
	{
		Point pt{ p.x + x, p.y + y };
		return pt;
	}

	Point operator+(const int d) const
	{
		Point pt{ d + x, d + y };
		return pt;
	}
};

int main()
{
	int n1 = 10;
	Point p1{ 1, 1 };
	Point p2{ 2, 2 };

	Point ret1 = p1 + p2; // p1.operator+(Point) 
	Point ret2 = p1 + n1; // p1.operator+(int) 
	Point ret3 = n1 + p1; // ??? -> n1.operator+(Point) -> error
}

연산자 재정의 주의사항

객체 상태가 변경되지 않은 연산자는 const member function 으로 해야 한다.
• 「p1 + p2」 → p1, p2 둘다 변경하지 않기에 "상수" 멤버 함수로 작성
• 「p1+=p2」 → p1 을 변경 하기 때문에 "비상수" 멤버 함수 작성 필요하며 p1 은 const 객체이면 안된다.

class Point
{
	int x{ 0 };
	int y{ 0 };
public:
	Point() = default;
	Point(int x, int y) : x{ x }, y{ y } {}

    // 상수 멤버 함수로 작성하였으며
	// 상수 객체 p1 이라도 "p1 + p2" 하고 싶다.
	Point operator+(const Point& p) const
	{
		Point pt{ p.x + x, p.y + y };
		return pt;
	}

	// "비 상수" 멤버 함수로 작성하였으며
    // 이 형태에서도 p1 이 상수 객체라면 "p1 += p2" 는 할 수 없기에 비상수 객체로 받아야 한다.
	Point& operator+=(const Point& p)
	{
		x += p.x;
		y += p.x;
		return *this;
	}
};

int main()
{
	const Point p1{ 1, 1 };
	Point p2{ 2, 2 };

	auto ret = p1 + p2; // ok --> p1.operator+(p2)

	p2 += p1; // ok
	p1 += p2; // ?? -> error
}



• 인자가 모두 primitive type 경우는 overloading 할 수 없다.
 → 한 개 이상은 반드시 사용자 정의 타입
• 인자 개수를 변경할 수 없다.
• default parameter 사용할 수 없다.
• [], (), ->, = 연산자는 멤버 함수로만 만들 수 있다.
• 새로운 연산자를 만들 수 없으며
 「.」 「.*」 「::」 「?:」 sizeof, typeid static_cast dynamic_cast reinterpret_cast const_cast  연산자는 재정의 할 수 없다. 
• 연산자 우선 순위는 변경할 수 없다.

int operator+(int a, int b) // error

int operator+(Point a, int b = 0) // error (디폴트 파라미터 X)

int operator+(Point p1, Point p2, Point p3) // error (+는 이항 연산자)

 

 

📌 [C++] 상수 멤버함수 const member function

 

[C++] 상수 멤버함수 const member function

상수 멤버 함수 (const member function)• 컴파일러에게 상수 멤버 함수인 것을 알게 해주는 것• 멤버 함수의 괄호() 뒤쪽에 const 키워드 사용 함수 선언과 구현으로 분리하는 경우 양쪽에 모두 붙인

zoosso.tistory.com

반응형

댓글