11. 연산자 오버로딩

11.1 연산자 오버로딩?

: 클래스 내에서 사용되는 연산자들에 다중적인 의미를 부여하는 다형성의 한 예이다.

  • 여태까지 클래스들의 배열의 합을 이렇게 나타낸 반면
for(int i = 0; i < 20; i++)
{
	object_Sum[i] = object_A[i] + object_B[i];
}
  • 연산자 오버로딩을 이용하면 간단하게 나타낼수 있다.
object_Sum = object_A + object_B;

: 내부 계산은 드러내지 않고, 단지 두 객체를 더하고 있다!

11.2 연산자 오버로딩의 예

  • Time을 측정하는 클래스이다.

함수를 보고 알 수 있는점!

  • 매개변수를 참조를 사용함으로써 value로 받을 때보다 메모리를 절약하고, 더 빠르다.

  • value값으로 보낸다는 것은 객체인 sum이 파괴되기 전에 프로그램이 sum객체의 복사본을 생성하고, 반환한다는 것이다.

반환값은 참조값이 아닌데, 참조를 한다면 어떻게 될것인가?

: 함수 특성- 덧셈으로 인해 새로운 값이 반환되어야 하므로 새로운 객체 sum을
만들어 준것이다.

  • 이렇게 한다는 것인데

    -> sum 객체 자신을 보내주는 것인데, 메모리 상으로 문제가 있다.
    왜냐하면 Sum함수에서 sum객체는 지연변수이므로 해제가 될 것인데, 참조를 반환 한다는 것은 이미 해제된 메모리를 반환한다는 것이므로 문제이다.
  • 예제

  • 결과 : 이상은 없지만, 경고 메시지 나타난다.
    지역객체 sum이 사라지므로 계산완료된 임시객체가 반환되는 듯 하다.
    만약에 내가 total로 받지 않는 상태에서 더한 결과의 참조값을 사용한다면 문제다.

객체 생성과 동시에 초기화, 선언 후 초기화 차이점..

  • Sum 함수를 레퍼런스로 반환할 경우.

  • 선언 후, 초기화

  • 객체 생성과 동시에 초기화

    : 임시객체 생성값이 total에 저장된것이다.

이동생성자를 만든다면..?


-> 위에서 생략된 생성자가 호출되는 것을 확인할 수 있찌만, 생성과 동시에 사라지므로 이를 우리가 처리해야한다?

알아야 할점

지역변수에 대한 참조와 임시 객체에 대한 참조를 리턴하면 안된다. 함수가 종료하고, 지역변수나 임시 객체가 사라질때 그러한 참조는 존재하지 않은 데이터에 대한 참조가 되기 때문이다.

operator + 로 연산하기

11.3 friend의 도입

: 외부의 함수를 어떤 class의 프랜드로 만들면, 그 프렌드 함수는 클래스의 멤버함수들이 갖는 것과 동등한 접근 권한을 가진다.

  • 클래스 내의 private 멤버에 접근이 가능하다.
  • 하지만 클래스의 멤버 함수는 아니다.

<< 연산자의 오버로딩에서 friend.

: 클래스 내에서 friend 를 사용하는 이유는 두개의 객체를 사용하고 있지만,
ostream 클래스 객체를 첫번째 피연산자로 사용하고 있기 때문이다.

os << Object;

만약에 <<오버로딩하기 위한다면 operator + 처럼 자신의 클래스가 첫번째 피연산자가 되어야 하는 것인데

Object << os;

  • 이렇게 하면, 출력을 할 수 없을 뿐 아니라,혼동을 주게된다.

  • << 이항연산자에서 첫번째 피연산자로 ostream이 와야한다.
    ostream 클래스는 c++ 표준이므로 직접 클래스 내부에서 Object 타입의 객체를 인수로 받아 << 연산자 오버로딩을 만들 수 없다.
    (c++ 표준은 사용자가 수정 불가능하다)

<< 오버로딩에서 & 사용하는 이유

os << object의 경우에는 정상적으로 출력이 가능하지만,,
os << "출력 결과는 " << object1 는 출력이 불가능하다.
: 체이닝을 하기 위해서 참조값을 반환하는 것이다.

cout << x << y; 의 경우
(cout << x ) << y;
cout << x 가 먼저 이루어진후에 ostream이 복사본이 아닌 자신의 값으로 반환을 해야 y도 출력이 가능하므로 참조형 타입으로 반환을 한것이다!

  • cout << "출력 결과는 " << object1; 진행과정
    1) cout << "출력 결과는" : 출력 후 반환받아서 다시
    2) cout << object1이 되는 것이고, object1이 출력된다.

입출력 함수는 레퍼런스 타입으로 반환하고, friend 선언을 반드시 해야한다.

따빼씨 : 9.2 입출력 연산자 오버로딩

  • 소스코드
#include <iostream>
using namespace std;

class Point
{
private:
	double m_x, m_y, m_z;

public:
	Point(double x = 0.0, double y = 0.0, double z = 0.0)
		: m_x(x), m_y(y), m_z(z)
	{}

	friend std::ostream& operator << (std::ostream &out, const Point &point)
	{
		out << "( " << point.m_x << ", " << point.m_y << ", " << point.m_z << " )";

		return out;
	}
};

int main()
{
	Point p1(0.0, 0.1, 0.2), p2(3.4, 1.5, 2.0);
	cout << p1 << p2;
}

파일 입출력에도 쉽게 사용가능하다는 장점이 잇다.


: 로그 찍을때 사용하면 됨.

입력 연산자 오버로딩

따빼씨 - 9.3 단항 연산자 오버로딩 하기

  • 부호 역으로 변경 및 뺄셈하기

  • Not 처리하기 : 목적에 따라서 만들어주자.

    : Not 오버라이딩에 의해 temp값이 bool 형식으로 변경된 것을 확인할 수 있다.

  • Not 처리 안할 경우 : 일반 생성자 형식으로 변경된 것을 확인할 수 있다.

따빼씨 - 9.4 비교 연산자 오버로딩 하기

  • 동일한지 다른지 구별하기

  • 비교 연산자를 이용해 정렬시키기

    : 이렇게 하면 정렬이 되지 않는다. 우리가 보기에는 int값으로만 비교하면되지 않음?! 이렇게 생각하지만, 컴파일러는 엄격하다!
    왜냐하면 class형식 내부에 유저가 직접 비교연산자를 구현하지 않았기 때문이다.
    class 내부의 멤버 값이 몇개 있고, 어떻게 비교 할지 정해주지도 않았는데,
    정렬 한다는 것은 말이 안된다!

비교연산자 함수 작성할때 주의사항


: > 요놈으로 하면 문제가 발생한다.

반드시 < 이 친구를 이용해 비교 연산자를 작성하자.

  • 반환부분의 부호를 바꿔줌으로써 오름차순? 내림차순인지 유저가 결정할 수 있따.

좋은 웹페이지 즐겨찾기