строку объекту типа String, параметр
Итак, выбора нет. Чтобы присвоить C- строку объекту типа String, параметр должен иметь тип const char*.
Хранение в _string прямой ссылки на C-строку, адресуемую sobj, порождает и иные сложности. Мы не знаем, на что именно указывает sobj. Это может быть массив символов, который модифицируется способом, неизвестным объекту String. Например:
char ia[] = { 'd', 'a', 'n', 'c', 'e', 'r' };
String trap = ia; // trap._string ссылается на ia
ia[3] = 'g'; // а вот это нам не нужно:
// модифицируется и ia, и trap._string
Если trap._string напрямую ссылался на ia, то объект trap демонстрировал бы своеобразное поведение: его значение может изменяться без вызова функций-членов класса String. Поэтому мы полагаем, что выделение области памяти для хранения копии значения C-строки менее опасно.
Обратите внимание, что в операторе присваивания используется delete. Член _string содержит ссылку на массив символов, расположенный в хипе. Чтобы предотвратить утечку, память, выделенная под старую строку, освобождается с помощью delete до выделения памяти под новую. Поскольку _string адресует массив символов, следует использовать версию delete для массивов (см. раздел 8.4).
И последнее замечание об операторе присваивания. Тип возвращаемого им значения – это ссылка на класс String. Почему именно ссылка? Дело в том, что для встроенных типов операторы присваивания можно сцеплять:
// сцепление операторов присваивания
int iobj, jobj;
iobj = jobj = 63;
Они ассоциируются справа налево, т.е. в предыдущем примере присваивания выполняются так:
iobj = (jobj = 63);
Это удобно и при работе с объектами класса String: поддерживается, к примеру, следующая конструкция:
String ver, noun;
verb = noun = "count";
При первом присваивании из этой цепочки вызывается определенный ранее оператор для const char*. Тип полученного результата должен быть таким, чтобы его можно было использовать как аргумент для копирующего оператора присваивания класса String. Поэтому, хотя параметр данного оператора имеет тип const char *, возвращается все же ссылка на String.
Операторы присваивания бывают перегруженными. Например, в нашем классе String есть такой набор:
// набор перегруженных операторов присваивания
String& operator=( const String & );
String& operator=( const char * );
Отдельный оператор присваивания может существовать для каждого типа, который разрешено присваивать объекту String. Однако все такие операторы должны быть определены как функции-члены класса.
Содержание Назад Вперед