#include <iostream>
#include <string.h>
#define NO_ASSIGN(T) T(const T& rhs); \
T& operator= (const T& rhs);
using namespace std;
class String {
struct Srep;
Srep *rep;
public:
class Cref;
class Range{};
String();
String(const char*);
String(const String&);
String& operator= (const String&);
String& operator= (const char*);
~String();
void check(int i) const {
if (i<0 || rep->sz <= i) throw Range(); //虽然前置声明类,但编译器并不知道类里有sz这个成员,编译出错。
}
char read(int i) const { return rep->s[i]; }
void write(int i, char c) {
rep = rep->get_new_copy();
rep->s[i] = c;
}
Cref operator[] (int i) {
check(i); return Cref(*this, i);
}
char operator[] (int i) const {
check(i);
return rep->s[i];
}
int size() const { return rep->sz; }
};
struct String::Srep {
Srep(int nsz, const char *p) {
n = 1;
sz = nsz;
s = new char[sz+1];
strcpy(s, p);
}
~Srep() { delete []s;}
Srep* get_new_copy() {
if (n == 1) return this;
n--;
return new Srep(sz, s);
}
void assign(int nsz, const char *p) {
if (sz != nsz) {
delete []s;
sz = nsz;
s = new char[sz+1];
}
strcpy(s, p);
}
char *s;
int sz;
int n;
NO_ASSIGN(Srep)
};
class String::Cref {
friend class String;
String& s;
int i;
Cref(String& ss, int index) : s(ss), i(index) { }
public:
void operator= (char ch) {
s.write(i,ch);
}
operator char() const { return s.read(i);}
};
String::String() {
rep = new Srep(0,"");
}
String::String(const String& rhs) {
rhs.rep->n++;
rep = rhs.rep;
}
String::String(const char* ch) {
rep = new Srep(strlen(ch), ch);
}
String& String::operator=(const String& rhs) {
if(this == &rhs) return *this;
rhs.rep->n++;
if(--rep->n == 0) delete rep;
rep = rhs.rep;
return *this;
}
String& String::operator=(const char* ch) {
if (rep->n == 1)
rep->assign(strlen(ch), ch);
else {
rep = new Srep(strlen(ch), ch);
}
return *this;
}
为了解决上述问题。不要把成员函数写成内联的。而是在Srep,Cref定义之后写。
#include <iostream>
#include <string.h>
#define NO_ASSIGN(T) T(const T& rhs); \
T& operator= (const T& rhs);
using namespace std;
class String {
struct Srep;
Srep *rep;
public:
class Cref;
class Range{};
String();
String(const char*);
String(const String&);
String& operator= (const String&);
String& operator= (const char*);
~String();
void check(int i) const;
char read(int i) const;
void write(int i, char c);
Cref operator[] (int i);
char operator[] (int i) const;
int size() const;
};
class String::Cref {
friend class String;
String& s;
int i;
Cref(String& ss, int index) : s(ss), i(index) { }
public:
void operator= (char ch) {
s.write(i,ch);
}
operator char() const { return s.read(i);}
};
struct String::Srep {
Srep(int nsz, const char *p) {
n = 1;
sz = nsz;
s = new char[sz+1];
strcpy(s, p);
}
~Srep() { delete []s;}
Srep* get_new_copy() {
if (n == 1) return this;
n--;
return new Srep(sz, s);
}
void assign(int nsz, const char *p) {
if (sz != nsz) {
delete []s;
sz = nsz;
s = new char[sz+1];
}
strcpy(s, p);
}
char *s;
int sz;
int n;
NO_ASSIGN(Srep)
};
String::String() {
rep = new Srep(0,"");
}
String::String(const String& rhs) {
rhs.rep->n++;
rep = rhs.rep;
}
String::String(const char* ch) {
rep = new Srep(strlen(ch), ch);
}
String& String::operator=(const String& rhs) {
if(this == &rhs) return *this;
rhs.rep->n++;
if(--rep->n == 0) delete rep;
rep = rhs.rep;
return *this;
}
String& String::operator=(const char* ch) {
if (rep->n == 1)
rep->assign(strlen(ch), ch);
else {
rep = new Srep(strlen(ch), ch);
}
return *this;
}
void String::check(int i) const {
if (i<0 || rep->sz <= i) throw Range();
}
char String::read(int i) const { return rep->s[i]; }
void String::write(int i, char c) {
rep = rep->get_new_copy();
rep->s[i] = c;
}
String::Cref String::operator[] (int i) {
check(i);
return Cref(*this, i);
}
char String::operator[] (int i) const {
check(i);
return rep->s[i];
}
int String::size() const { return rep->sz; }
int main() {
return 0;
}
由此可见c++的编译器是顺序编译的。即使在同一个文件里,也要注意先后顺序的问题。
如果你定义struct Srep 也会报错。因为在String里声明Screp是嵌套类,在String的域名空间里。与全局控件是不同的。