AcceleratedC++/Chapter11 | AcceleratedC++/Chapter13 |
~cpp class Str { public: typedef Vec<char>::size_type size_type; Str() {} Str(size_type n, char c):data(n, c) { } Str(const char* cp) { std::copy(cp, cp+std::strlen(cp), std::back_inserter(data)); } template<class In> Str(In b, In e) { std::copy(b, e, std::back_inserter(data)); } private: Vec<char> data; }
~cpp Str s("hello"); // s를 생성한다. Str t = "hello"; // t를 초기화 한다. s = "hello"; // 새로운 값을 s에 대입한다.
~cpp s="hello" s=Str("hello"); // 의 임시객체를 만들어서 만들어진 임시객체가 디폴트 복사 생성자를 통해서 할당되게 된다.
~cpp cin>>s; cout<<s; s[i]; s1 + s1
~cpp class Str{ public: // 이전의 생성자들 char& operator[](size_type i) { return data[i]; } const char& operator[](size_type i) const { return data[i]; } private: Vec<int> data; };이 구현의 세부적인 작동방식은 모두 Vec 클래스로 위임하였다. 대신에 const 클래스와 const 가 아닌 클래스에 대한 버전을 제공하였고, 표준 string 함수와의 일관성 유지를 위해서 string 대신에 char& 형을 리턴하도록 하였음.
~cpp cin>>s; cin.operator>>(s); // istream 을 우리가 만든 객체가 아니기 때문에 재정의할 수 없다. s.operator>>(cin); // 표준 istream 의 형태가 아니다. s>>cin상기와 같은 이유로 operator>>는 비멤버함수로서 선언이 되어야 한다.
~cpp std::istream& operator>>(std::istream&, Str&); std::ostream& operator<<(std::ostream&, const Str&); ostream& operator<<(ostream& os, const Str& s) { for(Str::size_type i=0; i!= s.size(); ++i) os<<s[i]; return os; }위의 식 처럼 사용하기 위해서는 Str::size() 가 정의 되어야한다.
~cpp class Str{ public: size_type size() const { return data.size(); } // 이전과 동일 }
~cpp istream& operator>>(istream& is, Str& s) { s.data.clear(); // compile error. private 멤버로 접근 char c; while(is.get(c) && isspace(c)) // 입력이 있고 값이 공백이라면 무시 ; if(is) { // EOF를 만나면 입력 스트림을 false 값을 리턴한다. do s.data.push_back(c); // compile error. private 멤버로 접근 while(is.get(c) && !isspace(C)); if(is) // 입력중 공백 문자를 만났을 경우 방금전에 입력으로 들어왔던 한문자를 무시한다. is.unget(); } return is; }상기의 함수는 Str 자료형에 입력을 하기 때문에 Str 형에 대한 쓰기 권한이 필요하다. 그러나 9.3.1절처럼 단순히 입력 함수를 만들게 되면 일반 사용자가 객체의 내부 구조를 건드릴 수 있는 인터페이스를 제공하는 꼴이 되기 때문에 옳지 못하다.
~cpp class Str { friend std::istream& operator>>(std::istream&, Str&); };friend 함수는 접근제어 레이블에 영향을 받지 않기 때문에 어디에 선언을 해도 무관하나, 가능하면 클래스 선언의 최초 부분에 놓는 것이 좋다.
~cpp s1 + s2 + s3;
~cpp Str operator+(const Str&, const Str&);그리고 operator+=() 역시도 구현해야할 필요가 있다.
~cpp class Str { // input operator implemented in 12.3.2/216 friend std::istream& operator>>(std::istream&, Str&); public: Str& operator+=(const Str& s) { std::copy(s.data.begin(), s.data.end(), std::back_inserter(data)); return *this; } // as before typedef Vec<char>::size_type size_type; Str() { } Str(size_type n, char c): data(n, c) { } Str(const char* cp) { std::copy(cp, cp + std::strlen(cp), std::back_inserter(data)); } template <class In> Str(In i, In j) { std::copy(i, j, std::back_inserter(data)); } char& operator[](size_type i) { return data[i]; } const char& operator[](size_type i) const { return data[i]; } size_type size() const { return data.size(); } private: Vec<char> data; }; // output operator implemented in 12.3.2/216 std::ostream& operator<<(std::ostream&, const Str&); Str operator+(const Str&, const Str&);상기에서 구현된 operator+= 는 Vec를 copy함수를 이용해서 구현하였다.
~cpp Str operator+(const Str& s, const Str& t) { Str r =s; r += t; return r; }지역변수로 생성된 r를 복사생성자를 통해 생성된 임시 객체로 리턴시킨다.
~cpp Str greeting = "Hello, " + name + "!";상기의 문장은 다음과 동일한 순서로 동작하게 된다.
~cpp Str temp1("Hello, "); Str temp2 = temp1 + name; Str temp3("!"); Str greeting = temp2 + temp3;이런식으로 동작하게 하면 임시 변수의 생성으로 인한 오버헤드가 상당함으로 알 수 있다. 이런 문제를 해결하기 위해서 string 클래스는 자동변환에 의존하지 않고, 피연산자들의 모든 조합에 대해 결합 연산자를 제공한다.
~cpp Vec<string> p = frame(42);원래의 의도 : 42라는 글자에 테두리가 처진 결과
~cpp class Student_info { public: operator double(); // ... } ... vector<Student_info> vs; ... double d = 0; d += vs[i]; // 이와 같이 형변환을 할 수 있다.
~cpp if (cin>>x) { /* ... */ } cin>>x if (cin) { /* ... */ }이경우 istream 은 void *를 리턴하게 된다.
~cpp class Str{ public: operator char* (); operator const char* () const; // 이전과 동일 private: Vec<char> data; }; Str s; ifstream in(s);하단의 코드가 올바르게 동작하지 못한다. 변환되는 형이 요구되는 형과 전혀 맞지 않기 때문이다.
c_str() | string 내부의 char*를 리턴한다. 따라서 사용자가 delete를 할 수는 없지만 포인터를 얻어서 수정할 수 있다. |
data() | c_str()과 비슷하지만 '\0'로 종료되는 문자열이 아닌 배열을 리턴한다. |
copy(char* ) | 인자로 받은 char*의 공간에 내부의 문제들을 복사해 넣는다. char*공간은 프로그램가 할당하고 해제하는 공간이다. |