공부/C++

[C++] 10-4. cout, cin 그리고 endl

knhoo 2024. 11. 27. 11:17
728x90

다음은 C++의 콘솔 입출력에 사용되는 cout과 endl의 이해를 돕기 위한 예제이다.

#include <iostream>
namespace mystd { //cout과 endl을 직접 구현하기 위해 선언한 이름공간
	using namespace std;//이 지역 내에서만 유효한 선언

	class ostream {
	public:
		//<<dustkswk dhqjfheld
		void operator<<(const char* str) {
			printf("%s", str);
		}
		void operator<<(char str) {
			printf("%c", str);
		}
		void operator<<(int num) {
			printf("%d", num);
		}
		void operator<<(double e) {
			printf("%g", e);
		}
		void operator<< (ostream& (*fp)(ostream& ostream)) {
			fp(*this);
		}
	};
	ostream& endl(ostream& ostm) {
		ostm << '\n';
		fflush(stdout);//버퍼 비우기
		return ostm;
	}
	ostream cout;
}

int main(void) {
	using mystd::cout;//mystd내에 선언된 cout과 endl 사용
	using mystd::endl;
	cout << "Simple String"; //cout.operator<<("Simple String");
	cout << endl;//cout.operator<<(endl);
	cout << 3.14;//cout.operator<<(3.14);
	cout << endl;//cout.operator<<(endl);
	cout << 123;//cout.operator<<(123);
	endl(cout);
	return 0;
}

위의 예제는 한가지 문제점을 지니고 있다.

  • cout<<123<<endl<<3.14<<endl;

이러한 형태의 문장은 컴파일 오류를 발생시킨다.

<<연산자는 왼쪽에서 오른쪽으로 진행이 된다. 따라서 위의 문장은 다음과 같은 순서로 연산이 이루어진다.

  • ( ( ( cout << (123) << endl ) << 3.14 ) << endl );

즉, 모든 <<연산의 결과로는 cout이 반환되어야 한다.

그래야 연이은 <<연산을 진행할 수 있다.

 

그러나 앞의 예제의 <<연산자는 cout을 반환하지 않아서 컴파일 에러가 발생한 것이다.

 

앞서 보인 예제를 확장해보자.

#include <iostream>

namespace mystd {
	using namespace std;

	class ostream {
	//cout 객체의 참조값을 반환하는 형태로 확장
	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);
		}
	};

	//endl함수는 인자로 전달된 객체의 참조값을 반환하므로,
	//반환된 값을 재 반환하는 형태로 연산자를 오버로딩
	ostream& endl(ostream& ostm) {
		ostm << '\n';
		fflush(stdout);
		return ostm;
	}
	ostream cout;
}

int main(void) {
	using mystd::cout;
	using mystd::endl;
	cout << 3.14 << endl << 123 << endl;
	return 0;
}

 


<<,>> 연산자의 오버로딩

이번에는 앞서 정의한 Point 클래스를 대상으로 <<연산자와 >>연산자를 오버로딩 해 보고자 한다.

  • cout은 ostream 클래스의 객체이다.
  • ostream은 이름공간 std 안에 선언되어 있으며, 이의 사용을 위해서는 헤더파일 <iostream>을 포함해야한다.
#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) {
	//인자로 전달된 cout의 참조자를 통한 출력을 구성
	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;
}


이번에는 Point 클래스를 대상으로 한 >> 연산자의 오버로딩을 구현해보자.

  • cin은 istream 클래스의 객체이다.
  • istream은 이름공간 std 안에 선언되어 있으며, 이의 사용을 위해서는 헤더 파일 <iostream>을 포함해야 한다.
/* 문제 10-3
* main 함수가 보이는 대로 데이터의 입력이 가능하도록,
* 그리고 실행의 예에서 보이는 대로 출력이 이뤄지도록
* >>연산자를 오버로딩하자.
*/
#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& pos);
};

ostream& operator<<(ostream& os, const Point& pos) {
	//인자로 전달된 cout의 참조자를 통한 출력을 구성
	os << '[' << pos.xpos << ", " << pos.ypos << ']' << endl;
	return os;
}

istream& operator>>(istream& is, Point& pos) {
	//인자로 전달된 cout의 참조자를 통한 출력을 구성
	is >> pos.xpos >> pos.ypos;
	return is;
}


int main(void) {
	Point pos1;
	cout << "x, y 좌표 순으로 입력: ";
	cin >> pos1;
	cout << pos1;

	Point pos2;
	cout << "x, y 좌표 순으로 입력: ";
	cin >> pos2;
	cout << pos2;
	return 0;
}

728x90