Главная->Інформатика та програмування->Содержание->Класс String с использованием операции new

ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 10) онлайн

Класс String с использованием операции new

Операция new часто используется в конструкторах классов. Для примера мы мо- дифицируем класс String, который рассматривали в примере STRPLUS главы 8 «Перегрузка операций». Мы можем устранить возможный дефект этого класса, возникающий, когда все объекты класса String занимают одинаковое количество памяти. Строки, занимающие меньший объем памяти, расходуют память впус- тую, а строки, которые ошибочно сгенерированы больше, чем предоставленный им объем, могут привести к ошибке программы, так как они выходят за пределы массива. В нашем следующем примере мы используем операцию new для выде- ления ровно необходимого количества памяти. Вот листинг программы NEWSTR:

// newstr.cpp

// использование оператора new для выделения памяти под строку #include  <iostream> #include <cstring>     //для strcpy(), и т.д. using namespace std; ///////////////////////////////////////////////////////////

class String

{

  private:

    char* str;          // указатель на строку

  public:

    String ( char* s )  // конструктор с одним параметром

      {

        int length = strlen ( s );     // вычисляем длину строки

        str = new char [ length + 1 ]; // выделяем необходимую память

        strcpy ( str, s );             // копируем строку

      }

    ~String ( )         // деструктор

      {

        cout << "Удаляем строку\n";

        delete [ ] str; // освобождаем память

      }

    void display ( )    // покажем строку на экране

      {

        cout << str << endl;

      }

};

///////////////////////////////////////////////////////////

int main ( )

{

  String s1 = "Тише едешь – дальше будешь.";

  cout << "s1 = ";

  s1.display ( );

 

  return 0;

}

 

Результат работы программы будет следующим:

S1 - Тише едешь - дальше будешь. Удаляем строку

Класс String имеет только одно поле str, являющееся указателем на char. Он будет указывать на строку, содержащуюся в объекте класса String. Здесь не бу- дет массива, содержащего строку. Строка хранится в другом месте, а в классе String есть только указатель на нее.

Конструктор в программе NEWSTR

Конструктор в этом примере имеет один аргумент: указатель на строку char*. С его помощью, используя операцию new, выделяется память для строки, на ко- торую будет указывать указатель str. Затем конструктор использует функцию strcpy() для копирования строки в выделенный участок памяти.

Деструктор в программе NEWSTR

Мы нечасто использовали деструктор в наших примерах, но теперь он нам необ- ходим для освобождения памяти, выделенной с помощью операции new. При создании объекта мы выделяем для него память, и будет вполне разумным осво- бодить эту память после того, как объект уже использован. Как вы могли заме- тить в главе 6, деструктор — это функция, которая вызывается автоматически

при удалении объекта. В программе NEWSTR деструктор выглядит следующим об- разом:

~String() {

  cout << "Удаляем строку.\n";   delete [ ] str;

}

Деструктор возвращает системе память, выделенную при создании объекта. Мы можем вывести в конце программы сообщение о том, что деструктор вы- полнил свою функцию. Объекты (как и другие переменные) обычно уничтожа- ются, когда функция, в которой они определены, заканчивает свою работу. Де- структор гарантирует, что память, выделенная для объекта класса String, будет возвращена системе при уничтожении объекта, а не останется неопределенной.

Мы должны заметить, что при использовании деструктора, как это показано в примере NEWSTR, могут возникнуть некоторые проблемы. При копировании одного объекта класса String в другой в строке s1-s2 в действительности проис- ходит копирование указателя на реальную строку. Теперь оба объекта указыва- ют на одну и ту же строку. При удалении строки деструктор удалит один указа- тель на строку, а указатель другого объекта будет указывать уже на что-то другое. Мы можем этого не заметить, так как процесс удаления объектов для нас невидим, например когда заканчивает свою работу функция, в которой был создан локальный объект. В главе 11 мы рассмотрим, как создать деструктор, который подсчитывает, сколько объектов класса String указывают на строки.

 

27