Coding/C & C++

C++ 연산자 오버로딩 1(기본 연산자, 단항 연산자, << 연산자)

heyoon2j 2020. 2. 26. 19:41

 C++ 연산자 오버로딩 1(기본 연산자, 단항 연산자)

ㆍ 기본 연산자 오버로딩

- operator라는 함수 이름을 사용하여 오버로딩

- 객체도 기본 자료형 데이터처럼 연산이 가능하도록 취급할 수 있다.

- 연산자 오버로딩을 하는 방법으로는 두 가지 방법이 있다(멤버함수, 전역함수)

 

1. 멤버함수에 의한 연산자 오버로딩

- Point pos3 = pos1 + pos2; 

    => pos1 + pos2 == pos1.operator+(pos2)

 

2. 전역함수에 의한 연산자 오버로딩

- Point pos3 = pos1 + pos2;

     => pos1 + pos2 == operator+(pos1, pos2)

 

ex>

class Point

{

private:

     int xpos, ypos;

public:

     Point operator+(const Point& ref) const       // 멤버함수

     {

         Point pos(xpos+ref.xpos, ypos+ref.ypos);

         return pos;

     }

     friend Point operator-(const Point& pos1, const Point& pos2);         // 전역함수

};

 

Point operator-(const Point& pos1, const Point& pos2)

{

     Point pos(pos1.xpos-pos2.xpos, pos1.ypos-pos2.ypos);

     return pos;

}

 

 

ㆍ 단항 연산자 오버로딩

1. 멤버함수에 의한 연산자 오버로딩

- Point pos = ++pos1;   // 전위 증가

     => ++pos1 == pos1.operator++()

 

- Point pos = pos1++;  // 후위 증가

     => pos1++ == pos1.operator++(int)

 

 

2. 전역함수에 의한 연산자 오버로딩

- Point pos = ++pos1;   // 전위 증가

     => ++pos1 == operator++(pos1)

 

- Point pos = pos1++;  // 후위 증가

     => pos1++ == operator++(pos1, int)

 

 

ex>

class Point

{

private:

     int xpos, ypos;

public:

     Point& operator++()        // 전위 증가

     {

          xpos+=1;

          ypos+=1;

          return *this;

     }

     const Point operator++(int)        // 후위 증가

     {

        const Point pos(*this);

         xpos+=1;

         ypos+=1;

         return pos;

     }

     friend Point& operator--(const Point& pos);        // 전위 증가, 전역함수

};

 

Point& operator--(const Point& pos)

{

     pos.xpos-=1;

     pos.ypos-=1;

     return pos;

}

 

* 후위 증가 함수 반환형에 const가 붙은 이유는 반환 시 const 임시객체를 반환하여 (point++)++과 같은 멤버함수 호출을 막기 위해서이다.

=> (point++)++ == (const 임시객체 point)++

 

 

ㆍ 교환법칙 문제에 대한 해결

1. 교환법칙 문제 예

ex>

class Point

{

private:

     int xpos;

     int ypos;

public:

     ...

     Point operator*(const int times) const

     {

         Point pos(xpos*times, ypos*times);

         return pos;

     }

};

 

- Point operator*(const int times) const 함수의 경우, 아래와 같이 

=> pos*2 == pos.operator*(3) (o, 가능)

=> 2*pos == 3.operator*(pos) (x, 불가능)

 

 

2. 교환법칙 문제 해결 방법

- 2*pos가 pos*2이 되도록 오버로딩을 하는 것이다.

- 즉, operator*(2, pos)로 변환되도록 오버로딩 함수 재정의

 

ex>

class Point

{

private:

     int xpos;

     int ypos;

public:

     ...

     Point operator*(const int times) const

     {

         Point pos(xpos*times, ypos*times);

         return pos;

     }

     friend Point operator*(const int times, const Point& ref);    // 전역 함수로 설정

};

Point operator*(const int times, const Point& ref)

{

     return pos*times;

}

 

 

ㆍ << 연산자 오버로딩

1. cout, endl에 대한 간단한 예시

ex>

namespace simplestd

{

     class ostream

     {

     public:

         ...

         osteam& operator<<(int num)

         {

             printf("%d",num);

             return *this;

         }

         osteam& operator<<(ostream& (*fp)(ostream& ostm))

         {

             return fp(*this);

         }

     };

 

     ostream& endl(ostream& ostm)

     {

         ostm<<'\n';

         fflush(stdout);

         return ostm;

     }

     ostream cout;

}

 

 

2. << 연산자 오버로딩

- cout<<에 대해 오버로딩을 하기 위해서 멤버함수 형태로 정의하려면, ostream 클래스의 수정이 필요하다.  그렇기 때문에 이런 경우에는, 전역함수 형태의 오버로딩을 해줘야 한다.

  => cout<<객체 == cout.operator<<(객체)     // 멤버함수

  => cout<<객체 == operator<<(cout, 객체)     // 전역함수

 

ex>

class Point

{

private:

     int xpos;

     int ypos;

public:

     ...

     friend ostream& operator<<(ostream& os, const Point& ref);    // 전역 함수로 설정

};

ostream& operator<<(ostream& os, const Point& ref)

{

     os<<'['<<ref.xpos<<", "<<ref.ypos<<endl;

     return os;

}

 

* cin은 istream 클래스의 객체이다.