클래스를 사용중, 대부분 한 파일에서 쓴 경우가 많았습니다.
이번에는 iostream중, ostream 클래스를 간단하게 구현하여, 헤더파일, 클래스 파일을 나누려고 합니다.
저의 클래스 이름은 myPrint입니다. 최종 목표는 myPrint을 다른 파일에서 저만의 클래스 파일로 사용하는 것입니다.
main.cpp
// main.cpp
#include "myPrint.h"
using namespace std;
int main()
{
cout << " DDD" << endl << " ㅎㅎ ";
return 0;
}
iostream 처럼 저는 std라는 네임스페이스에 출력은 cout를 사용 할 예정입니다.
myPrint.h
// myPrint.h
// 헤더 중복정의를 피하기 위한 매크로
#ifndef NSPACE_H
#define NSPACE_H
#include <stdio.h>
// 선언부
namespace std
{
class ostream
{
private:
int len;
public:
ostream();
void print(const char* str);
void print(int i);
void print(double d);
ostream& operator<<(const char* str);
ostream& operator<<(int i);
ostream& operator<<(double d);
ostream& operator<<(ostream& (*f)(ostream&));
};
ostream& endl(ostream& m);
}
#endif // !NSPACE_H
extern std::ostream cout; // 전역 변수, 클래스 선언
헤더파일 선언부입니다.
헤더의 중복정의를 피하기 위하여
#ifndef , #define , #endif 선언을 해주어야합니다.
#ifndef MPRINT_H // MPRINT_H를 정의한적 없다면
#define MPRINT_H // #endif가 나오기 전까지, MPRINT_H를 정의해주세요.
~ code ~
#endif // 여기까지
stdio.h파일의 print()를 오버로딩하여, char* int , double 변수를 받게 해줍니다.
이는 연산자 오버로딩을 통하여, << 로 편하게 객체를 가지고 올 수 있게 합니다.
ostream& operator<<(ostream& (*f)(ostream&)); 의 의미는, ostream 함수 객체를 받겠다는 의미입니다.
이후에 myPrint.cpp의 cout 이란 전역 변수를 extern하여 클래스 선언을 해줍니다.
-> 이로써, 그냥 main.cpp에서 myPrint.h만 include하고, cout만 써도 클래스 객체를 마음대로 사용합니다.~
myPrint.cpp
// myPrint.cpp
#include "myPrint.h"
// 구현부
// namespace std를 생략 하고 싶다면 using namespace std; 선언해주면 됨
std::ostream::ostream() :len(0) {}
void std::ostream::print(const char* str) { len += printf("%s ", str); }
void std::ostream::print(int i) { len += printf("%d ", i); }
void std::ostream::print(double d) { len += printf("%lf ", d); }
// namespace인 std의 ostream 클래스 레퍼런스를 리턴값으로 받는 operator overlording 함수 구현
std::ostream& std::ostream::operator<<(const char* str) {
print(str);
return *this;
}
std::ostream& std::ostream::operator<<(int i) {
print(i);
return *this;
}
std::ostream& std::ostream::operator<<(double d) {
print(d);
return *this;
}
std::ostream& std::ostream::operator<<(ostream& (*f)(ostream&)) {
return f(*this);
}
std::ostream& std::endl(ostream& m)
{
printf("\n");
return m;
}
std::ostream cout;
실질적인 구현부입니다.
print() 함수를 오버로딩을 통하여, 여러 변수타입들을 선언할 수 있게 해줍니다.
연산자오버로딩 쪽을 쉽게 이해하자면
예를 들어 std::ostream& std::ostream::operator<<(const char* str)
리턴값은 ostream&를 받습니다. 클래스 레퍼런스입니다.
매개변수값은 const char* 을 받습니다. 상수인 char의 포인터입니다
즉, 연산자 오버로딩으로 << 를 사용시 매개변수를 받고, 리턴값으로 클래스의 레퍼런스를 준다는 의미입니다.