| 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*공간은 프로그램가 할당하고 해제하는 공간이다. |