728x90

황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!

https://search.shopping.naver.com/book/catalog/32436115747

 

C++ Programming : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

삽입 연산자의 중복

  • 출력 스트림에 데이터를 출력하는 << 연산자를 삽입 연산자(insertion operator) 혹은 삽입자라고 부른다.
  • 본래 << 연산자는 정수를 비트 단위로 시프트(shift)하는 C++의 기본 연산자이다.
  • 그런데 C++ 입출력 시스템은 다양한 값을 출력할 수 있도록 ostream 클래스에 << 연산자를 중복 작성하였다.


 

삽입 연산자의 실행 과정

cout << 'a' << 123 << endl;
  • 위의 코드는 객체, 입출력 스트림, 연산자 중복, 참조 매개 변수, 참조 리턴이 절묘하게 연결되어 있는 코드이다.

 

리턴 타입이 의미하는 것
  • ostream 클래스 내에 중복 작성된 모든 << 연산자들은 아래와 같이 ostream&를 리턴한다.
  • << 연산자는 출력 스트림에 데이터를 삽입한 후, 출력 스트림(*this)을 리턴하며 리턴 타입이 ostream&이므로 스트림의 참조가 리턴된다.
  • 만약 리턴 타입이 ostream이라면, 복사본(*this)이 리턴되고, 그 다음에 실행되는 << 연산은 복사된 스트림에 출력하게 되어, 연속되는 두 << 연산이 서로 다른 출력 스트림에 출력하게 된다.
ostream& operator << (char c); // 문자를 출력하는 << 연산자

 

구체적인 실행 과정
  • 구체적인 실행 과정은 아래의 그림과 같다.

1. cout << 'a'에서 << 연산자를 호출

  • 컴파일러는 위 코드를 아래와 같이 변형하여 컴파일한다.
  • 이 코드는 cout 객체 내의 operator<<(char c)를 호출하고 'a'를 매개 변수에 넘겨준다.
cout . << ('a')

 

 

2. cout의 연산자 함수 ostream& operator << (char c)가 실행된다.

ostream& operator << (char c) {
	... 현재 스트림 버퍼에 c('a')를 삽입한다.
    ... 버퍼가 차면 장치에 출력한다.
    return *this; // 이 스트림의 참조를 리턴한다.
}
  • operator<< (char c) 함수는 문자 'a'를 현재 스트림(cout)의 버퍼에 저장하고 꽉 차면 화면에 출력한다.
  • 그리고 *this 곧 현재 스트림에 대한 참조를 리턴한다.

 

3. << 123을 실행한다.

  • cout << 'a'의 실행 결과 cout의 버퍼에 'a'가 삽입되고 cout에 대한 참조가 리턴되었다.
  • 따라서, << 123은 cout << 123을 실행하는 것과 같고, 'a'가 들어 있는 cout의 버퍼에 123을 출력하는 것이다.
ostream& operator << (int n) {
	... 현재 스트림 버퍼에 n(123)을 삽입한다.
    ... 만일 버퍼가 차면 장치에 출력한다.
    return *this;
}
  • operator << (int n) 함수는 매개 변수 n에 전달된 123을 현재 스트림(cout) 버퍼에 저장한다.
  • 버퍼는 "a123"으로 변경되며, 적절한 시점에 화면에 출력된다.
  • 즉, << 연산자가 cout의 참조를 리턴함으로써 반복되는 << 연산자에 의해 출력되는 데이터들이 cout의 버퍼를 통하여 화면에 출력된다.

 

사용자 삽입 연산자( <<) 만들기

Point p(3, 4);
cout << p;
  • Point 객체를 출력할 수 있는 << 연산자가 C++ 입출력 시스템에 없기 때문에 직접 << 연산자를 작성해야 한다.
  • cout << p에 의해 객체 p가 출력되도록 << 연산자를 작성해보자.
  • cout << p는 외부에 작성된 연산자이므로 컴파일러는 아래와 같이 변형한다.
<< (cout, p);
  • 따라서, 이에 맞추어 외부 함수로 << 연산자 함수를 작성하자.
// << 연산자 함수
ostream& operator << (ostream& stream, Point a) {
	stream << "(" << a.x << "," << a.y << ")";
	return stream;
}
  • stream 참조 매개 변수에 cout이 전달되고, a에는 객체 p가 전달된다.
  • private x, y를 접근할 수 있도록 << 연산자 함수를 Point 클래스에 friend로 선언

 

사용자 정의 삽입 연산자 함수의 원형
  • 삽입 연산자 << 의 함수 원형은 아래와 같으며 둘 다 가능하다.
  • 또한, 이들 연산자 함수는 외부 함수로만 작성되어야 하며 UserClass의 private 멤버에 접근하는 경우, UserClass에 프렌드로 선언되어야 한다.
ostream& operator << (ostream& outs, UserClass obj);
ostream& operator << (sotream& outs, UserClass& obj);

 

추출 연산자의 중복

  • cin과 함께 사용되는 >> 연산자를 추출 연산자(extraction operator)라고 부른다.
  • 본래는 정수를 비트 단위로 오른쪽 시프트(shift)하는 C++의 기본 연산자이기에 istream 클래스에 중복 작성하였다.

 


사용자 추출 연산자(>>) 만들기

  • 앞서 살펴본 삽입 연산자의 실행 과정과 흡사하므로 빠르게 살펴보자.
  • Point 객체 p를 생성 후 cin >> 을 사용하여 키 입력을 받으면 컴파일 오류가 발생한다. => istream에는 Point 객체의 값을 받아들이는 >> 연산자가 없기 때문에 아래와 같이 변형하여 컴파일한다.
Point p; // 디폴트로 x=0, y=0
cin >> p; // 컴파일 오류

>> (cin, p);

 

  • 아래와 같이 외부 함수로 만들어주면 된다.
istream& operator >> (istream& ins, Point &a) { // >> 연산자 함수
	cout << "x 좌표>>";
	ins >> a.x;
	cout << "y 좌표>>";
	ins >> a.y;
	return ins;
}
  • 여기서 중요한 점이 2가지 있다.
  • 첫째, 두 번째 매개 변수를 참조 타입(Point& a)으로 선언하는데, 이는 원본 객체 p에 값을 쓰기 위해서이다. a를 참조 타입으로 사용하지 않으면(Point a), 키 값을 읽어 매개 변수 a에 저장하여도 원본 객체 p가 변하지 않기 때문이다.
  • 둘째, 이 연산자 함수가 private 멤버 x, y를 접근하도록, Point 클래스에 friend로 선언한다.

 

사용자 정의 추출 연산자 함수의 원형
  • cin >> 연산자의 일반적인 함수 원형을 알아보자.
istream& operator >> (istream& ins, UserClass& obj);
#include <iostream>
using namespace std;

class Point { // 한 점을 표현하는 클래스
	int x, y; // private 멤버
public:	
	Point(int x=0, int y=0) {
		this->x = x; 
		this->y = y;
	}
	friend istream& operator >> (istream& ins, Point &a); // friend 선언
	friend ostream& operator << (ostream& stream, Point a); // friend 선언
};

istream& operator >> (istream& ins, Point &a) { // >> 연산자 함수
	cout << "x 좌표>>";
	ins >> a.x;
	cout << "y 좌표>>";
	ins >> a.y;
	return ins;
}

ostream& operator << (ostream& stream, Point a) { // << 연산자 함수
	stream << "(" << a.x << "," << a.y << ")";
	return stream;
}

int main() {
	Point p; // Point 객체 생성
	cin >> p;  // >> 연산자를 호출하여 x 좌표와 y 좌표를 키보드로 읽어 객체 p 완성
	cout << p;  // << 연산자를 호출하여 객체 p 출력
}
728x90

'Programming Language > C++' 카테고리의 다른 글

[C++] 예외 처리  (1) 2023.12.27
[C++] 사용자 조작자 만들기  (1) 2023.12.21
[C++] 포맷  (1) 2023.12.21
[C++] ostream과 istream  (1) 2023.12.20
[C++] 입출력 기초  (1) 2023.12.20