[c++] friend, 연산자 중복복

프렌드 함수(friend function)

  • private와 달리 외부의 클래스나 함수가 자신의 내부 데이터를 사용하도록 허가
    • private 멤버도 접근 가능

함수 선언

  • 클래스 어디든 선언 가능
  • 클래스 멤버가 아니다.
  • 외부에 선언된 함수를 프렌드로 지정하여, 내부 멤버를 사용 가능하게 하는 것

프렌드 클래스

  • Employee의 내부 데이터에 대한 접근이 필요한 Manager.
    class Employee {
        int Salary;
        // Manager는 Employee의 전용 부분에 접근할 수 있다.
        friend class Manager;
        .....
    };
    
    void Manager::raiseSalary(Employee& e, int amount)
    {
        // salary를 참조하는 것이 허용된다.
        e.salary += amount;
    }
    

참고사항

  • 함수가 수행하는 작업이 오직 하나의 객체에만 관련된다면 멤버 함수로 정의한다.

  • 함수가 수행하는 작업이 두 개 이상의 객체와 관련된다면 프렌드 함수로 정의한다.

  • 프렌드 함수나 프렌드 클래스는 객체 지향의 중요한 원칙인 정보 은닉을 무너뜨린다.

    • 사용시 각별한 주의가 필요하다.

연산자 중복(operator overloading)

  • 연산자를 클래스 객체에 대해서도 적용할 수 있도록 중복하여 정의하는 것

    반환형 operator 연산자(매개변수목록)
    {
    ...... // 연산 수행
    }
    
    Vector operator+(const Vector&, const Vector&);
    

    alt text

  • 멤버, 전역 함수로 둘다 구현 가능

*컴파일러 연산

(v1 + v2) 를 작성할 경우
➔ 컴파일러가 v1.operator+(v2) 로 변경하여 실행

멤버 함수로만 구현가능한 연산자

alt text

중복할 수 없는 연산자

alt text

피연산자의 타입이 다른 연산

  • ex) 벡터의 스칼라 곱 연산
    • 첫번째,두번째 연산자의 위치가 중요
  • 교환법칙
    • 컴파일러가 자동으로 해주지 않는다.
    • 명시적으로 위치를 지정해서 연산자 함수를 작성하여야 한다.
      Vector operator*(Vector& v, double alpha); // v * 2.0 형태 처리
      Vector operator*(double alpha, Vector& v); // 2.0 * v 형태 처리
      

== 연산자의 중복

  • == 연산자와 != 연산자를 같이 정의하는 것이 좋다

<< 출력 연산자의 중복

  • 어떤 객체라도 << 를 통해 출력이 가능하도록 중복 정의 하는것이 가능하다.

  • 주의점으로 출력을 관장하는 cout은 ostream의 객체로서 해당 클래스 안에 operate<<() 함수를 정의해야 한다.

    • ostream 클래스는 컴파일러가 제공하는 라이브러리로 변경이 불가능. 따라서,
    • 전역 함수 형태로 연산자를 중복정의한다.
      ostream& operator<<( ostream& os, const Vector& v)
      {
      ......
      }
      
      • 연산의 결과 : 반드시 ostream 참조자를 반환하여야 한다.

>> 입력 연산자의 중복

istream& operator>>(istream& in, Vector& v)
{
	in >> v.x >> v.y;
	if (!in)
	v = Vector( 0, 0 );
	return in;
}

대입 연산자의 중복

  • 중복하지 않더라도 디폴트가 자동 생성
    • 디폴트 대입 연산자 : 한 객체의 모든 멤버들을 다른 객체로 복사
Vector& operator=(const Vector& v2)
{
	this->x = v2.x;
	this->y = v2.y;
	return *this; //주의:반드시 현재 객체의 참조자를 반환해야 한다.
}
  • 중복 정의 가능

증감 연산자의 중복

alt text

  • 피연산자의 개수가 하나이다.

후위 증가/감소 연산자

  • int 형 매개변수를 추가한다.

alt text

인덱스 연산자 []의 중복

alt text

  • 인덱스 범위를 벗어났을때 오류를 처리할 수 있다.
int& MyArray::operator[](int index) {
	// 인데스가 범위에 있지 않으면 중지
	assert(0 <= index && index < size);
	return data[index]; 
}

*assert() 함수

  • 디버깅 모드에서 개발자가 오류가 생기면 치명적일 것이라는 곳에 심어 놓는 에러 검출용 코드

중복시 유의점

  • 새로운 연산자를 선언 정의하는것은 불가능
  • 중복된 연산자는 클래스타입의 피연산자를 가져야한다.
  • +연산자를 중복하였다면, +=, -= 연산자도 중복하는것이 좋다.(일관성)