Minwoo Dev.

[C++] << 연산자 오버로딩, >> 연산자 오버로딩 , istream, ostream 본문

C++

[C++] << 연산자 오버로딩, >> 연산자 오버로딩 , istream, ostream

itisminu 2024. 7. 19. 13:37
728x90
반응형
SMALL

이번에는 입력과 출력을 담당하는 연산자에 대해서 오버로딩을 해 보겠다.

 

class Point{
private:
    int xpos, ypos;
public:
    Point(int x = 0, int y = 0):xpos(x),ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
};

 

이번에도 Point 클래스를 활용하여 보자.

 

 

위의 Point 클래스의 경우에, 출력을 아래와 같이 했을 때 어떻게 출력되는 게 좋겠는가 ?

cout<<pos1<<endl;

 

아마 ( 3 , 4 ) 혹은 [ 5, 3 ]과 같이 괄호, 그리고 콤마와 함께 출력되는 것이 Point클래스를 잘 출력하는 방법이 될 것이다.

 

이렇게 출력되도록 입출력 연산자를 오버로딩할 수 있다.

 

 

그러기 위해서는 ostream과 istream에 대해서 알아야한다.

 


ostream

  • 표준입출력스트림 (iostream)중에 하나이다.
  • #include<iostream>을 통해 불러온다.
  • "출력"을 담당한다.
#include<iostream>
namespace mystd{
    using namespace std;

    class ostream{
    public:
        ostream& operator<<(char * str){
            printf("%s", str);
            return *this;
        }
        ostream& operator<<(char str){
            printf("%c", str);
            return *this;
        }
        ostream& operator<<(int num){
            printf("%d", num);
            return *this;
        }
        ostream& operator<<(double e){
            printf("%g", e);
            return *this;
        }
        ostream& operator<<(ostream& (*fp)(ostream &ostm)){
            return fp(*this);
        }
    };
    ostream& endl(ostream & ostm){
        ostm << '\n';
        fflush(stdout);
        return ostm;
    }

    ostream cout;
}

 

위 코드는 ostream이 하는 동작을 비슷하게 구현한 mystd이다.

C++이 C언어를 기반으로 만들어졌기 때문에, <<을 통한 출력은 자료형에 따라 printf내부의 포맷팅 문자열이 다르게 적용되는 것을 확인할 수 있다.

 

 

istream

  • 표준입출력스트림(iostream) 중에 하나이다.
  • #include<iostream>을 통해 불러온다.
  • "입력"을 담당한다.

 

이제 Point 클래스의 입력과 출력을 구현해보겠다.

 

입출력 스트림의 오버로딩은 전역 함수로 작성하게 된다.

 

 

<< 연산자 오버로딩 (출력)

#include<iostream>
using namespace std;

class Point{
private:
    int xpos, ypos;
public:
    Point(int x=0, int y=0) : xpos(x), ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
    friend ostream &operator<<(ostream &, const Point &);
};

ostream& operator<<(ostream& os, const Point& pos){
    os << '[' << pos.xpos << ", " << pos.ypos << ']' << endl;
    return os;
}

int main(void){
    Point pos1(1, 3);
    cout << pos1;
    Point pos2(101, 303);
    cout << pos2;
    return 0;
}

 

실행 결과

 

 

위 코드에서 오버로딩 부분을 보자.

ostream& operator<<(ostream& os, const Point& pos){
    os << '[' << pos.xpos << ", " << pos.ypos << ']' << endl;
    return os;
}

 

출력은 ostream을 사용한다고 했었다.

그리고 우리가 출력을 할 때, 하나만 출력하는 것이 아니라 이어서 계속 출력하는 상황도 있을 것이다.

 

그럴 때 ostream의 참조값이 아닌 일반 ostream을 반환형으로 둔다면, 계속해서 이어서 출력하지 못하는 에러가 발생한다.

    cout << pos2<<"HI"<<222; // 반환형을 ostream& 으로 해야 이어서 쭉 출력함

 

왜냐하면 출력을 수행할 때, ostream&을 반환값으로 사용하면  ostream의 객체 주소값이 전달되는 것인데 이 객체 주소값을 다음 출력할 값으로 넘겨주게 되기 때문이다.

 

따라서 무조건 ostream& 을 반환형으로 작성해주어야 한다.

그리고 전역 함수이기 때문에 ostream 객체를 받아와야하고, 점도 매개변수로 받아온다.

cout을 통해 출력할 부분은 os<<"~~~" 와 같이 작성하면 된다.

 

그리고 마지막으로 꼭 !!! os를 반환해주어야 한다.

os를 반환하지 않으면 우리가 반환형을 ostream&으로 설정하여 연속적으로 출력할 수 있게 한 의미가 없다.

 

 

정리

  • 꼭!!@! ostream& 을 반환형으로 작성하자.
  • 꼭!!!! ostream 객체를 return 하자.

 


 

>> 연산자 오버로딩 (입력)

#include<iostream>
using namespace std;

class Point{
private:
    int xpos, ypos;
public:
    Point(int x=0, int y=0) : xpos(x), ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
    friend ostream &operator<<(ostream &, const Point &);
    friend istream &operator>>(istream &, Point &);
};

ostream& operator<<(ostream& os, const Point& pos){
    os << '[' << pos.xpos << ", " << pos.ypos << ']' << endl;
    return os;
}

istream& operator>>(istream& is, Point& pos){
    is >> pos.xpos >> pos.ypos;
    return is;
}

int main(void){
    Point pos1;
    cout << "x, y를 입력하세요 : ";
    cin >> pos1;
    cout << pos1;
    return 0;
}

 

실행 결과

 

 

위 코드에서 >> 연산자 오버로딩 부분을 자세히 보자

istream& operator>>(istream& is, Point& pos){
    is >> pos.xpos >> pos.ypos;
    return is;
}

 

우선, >> 연산자는 입력 스트림을 사용하므로 istream을 사용한다.

그리고 << 연산자와 동일하게 연속적으로 값을 입력받기 위해 istream이 아닌 istream&을 반환값으로 설정한다.

입력할 값은 is>> "대입할 변수" 와 같은 형식으로 작성하고,

꼭 istream의 객체 값을 반환해준다.

 

 

정리

  • 꼭!!@! istream& 을 반환형으로 작성하자.
  • 꼭!!!! istream 객체를 return 하자.

 

 

 

 

Point 클래스가 아니더라도 다양한 클래스에 해당 클래스만의 입출력 , 사칙연산 방식을 연산자 오버로딩을 통해 구현할 수 있다!

728x90
반응형
LIST