Minwoo Dev.
[C++] << 연산자 오버로딩, >> 연산자 오버로딩 , istream, ostream 본문
이번에는 입력과 출력을 담당하는 연산자에 대해서 오버로딩을 해 보겠다.
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 클래스가 아니더라도 다양한 클래스에 해당 클래스만의 입출력 , 사칙연산 방식을 연산자 오버로딩을 통해 구현할 수 있다!
'C++' 카테고리의 다른 글
[C++] 윤성우의 열혈 C++ 11-2 C++ 기반의 데이터 입출력 문제풀이 (0) | 2024.07.21 |
---|---|
[C++] 윤성우의 열혈 C++ 11-1 깊은 복사를 하는 대입 연산자의 정의 문제풀이 (0) | 2024.07.21 |
[C++] 연산자 오버로딩에서의 교환법칙 (0) | 2024.07.19 |
[C++] 후위 증감연산자 오버로딩, pos++, pos-- (0) | 2024.07.19 |
[C++] 전위 증감 연산자 오버로딩, ++pos, --pos (0) | 2024.07.19 |