#include using namespace std; class MyString { public: MyString(); // A default constructor MyString(const char*); // A normal constructor MyString(MyString const& s); MyString& operator= (MyString const& s); ~MyString(); char getChar(const int& i) const; // No changes to this object void setChar(const int& i, const char& c); // Change this object void print() const; private: class Data { public: Data(); Data(const char*); Data(Data const& d); // Since only Fred can access a Fred::Data object, // you can make Fred::Data's data public if you want. // But if that makes you uncomfortable, make the data private // and make Fred a friend class via friend class Fred; char* text; unsigned count_; // count_ is the number of Fred objects that point at this // count_ must be initialized to 1 by all constructors // (it starts as 1 since it is pointed to by the Fred object that created it) }; Data* data_; }; MyString::Data::Data() : count_(1) { text = new char[1]; text[0] = '\0'; } MyString::Data::Data(const char* s) : count_(1) { text = new char[strlen(s)+1]; strcpy(text, s); } MyString::Data::Data(Data const& d) : count_(1) { text = new char[strlen(d.text) + 1]; strcpy(text, d.text); } MyString::MyString() : data_(new Data()) { } MyString::MyString(const char* s) : data_(new Data(s)) { } MyString::MyString(MyString const& s) : data_(s.data_) { ++data_->count_; } MyString& MyString::operator= (MyString const& s) { // DO NOT CHANGE THE ORDER OF THESE STATEMENTS! // (This order properly handles self-assignment) // (This order also properly handles recursion, e.g., if a Fred::Data contains Freds) Data* const old = data_; data_ = s.data_; ++data_->count_; if (--old->count_ == 0) delete old; return *this; } MyString::~MyString() { if (--data_->count_ == 0) delete data_; } char MyString::getChar(const int& i) const { return *(data_->text+i); } void MyString::setChar(const int& i, const char& c) { // This method might need to change things in *data_ // Thus it first checks if this is the only pointer to *data_ if (data_->count_ > 1) { Data* d = new Data(*data_); // Invoke Fred::Data's copy ctor --data_->count_; data_ = d; } data_->text[i] = c; } void MyString::print() const { cout << data_->text << " [" << data_->count_ << "]" << endl; }