단항 연산자의 멤버 함수로의 선언


  • 선언 형태
    Point operator-() const;
    Point operator++()
    Point operator++(int);
    bool operator!() const;
  • 사용 예시
    Point p1{10,20};
    Point p2 = -p1; //p1.operator-();로 변환
  • 이항 연산자와 차이점 간단하다 . 컴파일러가 해석을 하기위해 변환 할 때, 연관된 인자가 하나밖에 없기 때문에 뒤에 인자가 비어있다.
    
    Point p1{10,20};
    Point p2 = -p1; //p1.operator-();로 변환

예시 코드


class Point{

//중략

	Point operator-() const
	{
		return Point{ -xpos,-ypos };
	}

};

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

	Point p3 = -p1; //p1.operator-() 호출 됨
	p3.ShowPosition();
}

멤버 함수로 선언 시 한계점


  • 교환 법칙이 성립하도록 구현이 불가능할 수 있음

  • 예를들어 자료형이 다른 경우, 3(int), p1(Point)를 가정해 보면

  • p13은 함수 호출 가능, 3p1은 함수 호출 불가!

    class Point{
    
    //중략
    
    	Point operator*(int d) const //p1.operator*(3) 가 호출이 될 때 가능해야함
    	{
    		return Point{ xpos * d , ypos * d };
    	}
    	
    };
    
    int main()
    {
    	Point p1{ 2,3 };
    	
    	Point p2 = p1 * 3;//가능
    	Point p3 = 3 * p1; //불가능, 3.operator*(p1)이라고 해석 불가능
    
    }

    3은 상수이기 때문에 멤버 함수를 가지고 있을 수 없음, 문법적으로 성립이 불가능!
    이를 해결하기 위해 전역 함수 연산자 오버로딩을 이용하여 해결해보자

참고

💡

‘ - ’ 연산자는 단항, 이항 둘 다 사용 될 수 있다.

무슨 의미인가 잘 이해가 안 될 수 도 있다. 코드를 봐보자

int a = 10;

std::cout << -a << std::endl;

우리는 위에서 -가 이항 연산자로 사용될 때 어떻게 작성해야 하는지 배웠다. 하지만 - 는 단항으로도 사용 될 수 있다는 것을 우리는 이미 간단한 수학으로 알고있다.

이항 연산자의 전역 함수로의 선언( + , - , == , ≠ , > , < , etc)


  • Operator 오버로딩을 전역 함수로 선언 ( Point :: operator가 아님)

  • 왼쪽 피연산자도 매개변수로써 전달

    • 이러한 구현을 위해서는 함수를 firend로 선언하는 것이 일반적
  • 컴파일러는 연산자 멤버 함수와 연산자 전역 함수 둘 다 찾아본다.

    • 멤버 함수가 없으면 전역 함수를 찾아서 변환한다.
Point operator+ ( const Point& lhs, const Point& rhs);
Point opeartor- ( const Point& lhs, const Point& rhs);
bool operator== ( const Point& lhs , const Point& rhs);
bool operator< ( const Point& lhs, const Point& rhs);

Point p1{10,20};
Point p2{30,40};
Point p3 = p1 + p2; //p1.operator+(p2) 없을시에operator+(p1,p2); 로 해석
p3 = p1 - p2; //operator-(p1,p2);로 해석

if(p1 == p2) //operator==(p1,p2)로 해석
		//......

예시 코드


#include <iostream>

class Point
{
	friend Point operator*(Point p, int d);//해당 함수는 private에도 접근 가능
private:
	int xpos;
	int ypos;
public:
	Point(int x = 0, int y = 0)
		:xpos{ x }, ypos{ y } {}

	void ShowPosition() const
	{
		std::cout << "[" << xpos << "," << ypos << "]" << std::endl;
	}

	Point operator+(const Point& p) const //복사의 비용을 낮추기 위해서 const 참조자 사용, p의 값이 바뀌면 안되기 때문에
	{
		return Point{ xpos + p.xpos, ypos + p.ypos };
	}

	bool operator== (const Point& p) const
	{
		if (xpos == p.xpos && ypos == p.ypos)
			return true;
		else
			return false;
	}

	Point operator-() const
	{
		return Point{ -xpos,-ypos };
	}

};

Point operator*(Point p, int val) //전역함수로도 오버로딩 가능
{
	return Point{ p.xpos * val , p.ypos * val };
}

int main()
{
	Point p1{ 2,3 };
	
	Point p2 = p1 * 3;//가능

}

operator*(Point p, int val)를 전역 함수로 정의하여 오버로딩을 하였지만 p.xpos, p.ypos는 private으로 되어있기 때문에 접근이 불가능하다. 이때 접근을 하기 위해 friend로 선언해준다.

주의

class Point
{
	friend Point operator*(Point p, int val)
	{
		return Point{ p.xpos * val , p.ypos * val };
	}
private:
	int xpos;
	int ypos;

//......

};

friend함수를 위와 같이 함수 body를 class안에다 정의해도 해당 함수는 class의 멤버가 아니다. 전역 함수다!, 즉 앞에서 본 코드를 줄여서 작성한 것이다.

profile
개발로그

0개의 댓글