모두의 코드 내용을 공부하고 정리한 내용입니다.



오버로딩

  • 기존 정의되어 있는 것을 사용자가 원하는 것으로 재정의하는 것을 오버로딩이라 한다.
  • 함수 이름은 같지만 매개변수가 다르면 다른 함수로 인식한다
    void Func(int x) {}
    void Fucn(double x) {}
    // 두 함수는 다른 함수로 취급 => 매개변수가 다름
    


  • 리턴 타입은 다른 함수라고 판단하는 기준이 되지 않는다.
  • 매개변수 이름만 다른 것은 다른 함수라고 판단하지 않는다.



연산자 오버로딩

class A
{
public:
    int x = 3;
    int y = 10; 
};

int main()
{
    A object1;
    A object2;

    cout << object1 + object2 << endl;  // 오류!
}
  • 우리만의 클래스 객체 간의 연산이 필요하다면 연산자 오버로딩이 필요하다.
  • 원하는 객체를 매개변수로 받아 연산을 하고 결과를 리턴하는 함수를 만들 수 있다.
    int Add(const A& a, const A& b) {} 
    


  • 리턴타입 operator연산자(연산자가 받는 인자)
    • +, -, << 등 특정 타입의 객체를 피연산로 들오면 우리가 정한 작업을 하게 미리 정의를 할 수 있다.
    • 이것이 연산자 오버로딩이다.
int operator+(const A& a, const A& b)
{
    return a.x + b.x;
}
cout << object1 + object2;



오버로딩이 가능한 연산자자

  1. 산술 연산자
    • +, -, *, /, %
    • += 와 같은 복합 연산자도 가능하다.
      • 멤버 함수로 사칙연산 오버로딩경우 리턴을 값으로 리턴해야 한다.
      • 만약 레퍼런스로 리턴을 하면 생각했던 것과 다르게 작업한다. A a = b + c + b; 이것은 a = b * 2 + c 를 의도했을 것이다.
      • 하지만 실제로는 (b.plus(c)).plus(b)로 작업이 되는데 b 에는 (b + c) 가 들어가고, 거기에 다시 plus(b) 를 하게 된다면 (b+ c) + (b + c) 가 수행되서 생각과 다르게 결과값이 나온다.
  2. 입출력 연산자
    • <<, >>
  3. 단항 연산자
    • +, -, !
  4. 비교 연산자
    • >=, ==, >, !=
  5. 증감 연산자
    • ++, --
      • operator++(); : 전위 연산자 ex) ++a 값이 바뀐 자기 자신을 리턴
      • operator++(int x); : 후위 연산자 ex) a++ 값이 바뀌기 이전의 객체를 리턴
      • 여기서 인자는 단순히 전위 증감 연산자와 구별하기 위한 척도이다.
  6. 첨자 연산자
    • []
  7. 괄호 연산자
    • ()
  8. 논리 연산자
    • &&, ||
  9. 형변환 연산자
    • (자료형), 자료형()
  10. 대입 연산자
    • =
      • 멤버 함수 대입 연산자의 경우 레퍼런스로 리턴해야 한다.
      • 대입을 한 후에 해당 값으로 다시 연산을 수행하는게 아니기 때문이다.
      • 대입 연산자는 디폴트로 정의되어 있지만 얕은 복사를 한다.
      • 동적으로 메모리 관리하는 것이 있다면 직접 대입 연산자를 만들자
  11. 비트 연산자
    • <<, >>, &, |, ^
  12. 포인터 관련 연산자
    • *, &, ->, ->*
  13. 메모리 연산자
    • new, new[], delete, delete[]



오버로딩이 불가능한 연산자

  • ? 조건연산자
  • :: 범위 지정 연산자
  • sizeof 크기 연산자
  • . 멤버 선택 연산자
  • .* 포인터로 멤버 선택할 때 연산자



전역 함수 연산자 오버로딩 VS 멤버 함수 연산자 오버로딩


전역함수

class A
{
private:
    int x;
public:
    friend A operator + (const A& object1, const A& object2); // friend는 뒤에서 설명명
};

A operator + (const A& object1, const A& object2)
{
  return A(object1.x + object2.x); 
}
  1. A1 + A2
    • A 타입의 두 매개변수를 받아 오버로딩 된 + 연산을 실행한다.
    • 덧셈 결과를 A 타입으로 리턴한다.
  2. (A1 + A2) + A3
    • A1 + A2의 덧셈 결과도 A 타입이니
    • 덧셈 결과와 A3, 두 매개변수를 받아 오버로딩 된 + 연산을 실행한다.
    • 덧셈 결과를 A 타입으로 리턴한다.


멤버 함수

class A
{
private:
    int x;
public:
    A operator + (const A& object) 
    {
      return A(x + object.x); 
    }
};
  1. A1 + A2
    • 자기 자신 : A1
    • 인수 1개 : A2
    • 덧셈 결과를 A 타입으로 리턴한다.
  2. (A1 + A2) + A3
    • 자기 자신 : (A1 + A2) 덧셈 결과
    • 인수 1개 : A3
    • 덧셈 결과를 A 타입으로 리턴한다.



정리

  • 위에서 잠깐 이야기를 했는데 반환값을 다시 사용하느냐 안 하느냐에 따라 반환값을 달리 했다
  • 간단히 정리를 하자면
  1. 두 개의 동등한 객체 사이에서의 이항 연산자는 멤버 함수가 아닌 외부 함수로 오버로딩 하는 것이 좋다.

    (예를 들어 operator+(const A&, const A&) const)

  2. 두 개의 객체 사이의 이항 연산자 이지만 한 객체만 값이 바뀐다던지 등의 동등하지 않는 이항 연산자는 멤버 함수로 오버로딩 하는 것이 좋다.

    (예를 들어서 operator+= 는 이항 연산자 이지만 operator+=(const Complex&) 가 낫다)

  3. 단항 연산자는 멤버 함수로 오버로딩 하는 것이 좋다.

    (예를 들어 operator++ 의 경우 멤버 함수로 오버로딩)



friend

  • A 클래스에 friend로 B클래스가 선언되었다면 B클래스는 A클래스의 private에 접근이 가능하다.

    • 함수도 friend로 선언했다면 마찬가지로 private에 접근이 가능하다.
class A
{
private:
	int x;
public:
	int getA() const { return x; }
	int& getA() { return x; }

    friend void operator + (const A& object1, const A& object2);  // A의 친구로 지정.
};
void operator+(const A& object1, const A& object2)
{
	cout << object1.x + object2.x << endl; // friend이기에 직접 접근 가능

	// cout << object1.getA() + object2.getA() << endl; // private이여서 직접 접근 못함
  // 여기에서 getA()는 int getA() const { return x; }이다
  // 인수가 const객체이기 때문
}
int main()
{
	A a1(5);
	A a2(7);

	cout << a1.getA() + a2.getA() << endl;
  // 여기에서 getA()는 int& getA() { return x; }이다

	a1 + a2;  // 오버로딩한 + 호출
}
  • 원래는 private인 멤버 변수에 접근을 하지 못한다.
  • 그래서 public 멤버 함수로 Get함수를 만들어 접근을 하여 사용한다.
  • 하지만 friend를 사용하여 쉽게 접근할 수 있다.


  • 반대로 A클래스는 B클래스의 private에 접근하지 못한다.
    • 일방향적인 능력
  • 그런데friend 사용으로 인해 private 의미가 없어진다.
    • C++의 은닉성을 망친다.
    • 분명히 필요할 경우에만 사용하자.




개인 공부 기록용 블로그입니다.
틀린 부분 있으다면 지적해주시면 감사하겠습니다!!

카테고리:

업데이트:

댓글남기기