|
Программирование >> Решение нетривиальных задач
string s; char array[128]; s.buf = array; и организация памяти разрушается, когда эта строка покидает область действия. Простое закрытие при помощи модификатора private поля buf не помогает, если вы продолжаете обеспечивать доступ посредством функции. Листинг 7 показывает фрагмент простого определения строки, которое будет использоваться мной несколько раз в оставшейся части этой главы. (Упрощение, сделанное мной, свелось к помещению всего в один листинг; обычно определение класса и встроенные функции будут в заголовочном файле, а остальной код - в файле .cpp). Листинг 7. Простой строковый класс 1 class string 3 char *buf; 4 int length; длина буфера (не строки); 5 6 public: 7 virtual 8 ~string( void ); 9 string( const char *input str = ); 10 string( const string &r ); 12 virtual const string &operator=( const string &r ); 14 virtual int operator< ( const string &r ) const; 15 virtual int operator> ( const string &r ) const; 16 virtual int operator==( const string &r ) const; 18 virtual void print( ostream &output ) const; 19 ... 20 }; 21 ----------------------------------------------------------------22 inline string::string( const char *input str /*= */ ) 23 { 24 length = strlen(input str) + 1; 25 buf = new char[ length ]; 26 strcpy( buf, input str ); 27 } 28 ----------------------------------------------------------------29 inline string::string( const string &r ) 30 { 31 length = r.length; 32 buf = new char[ length ]; 33 strcpy( buf, r.buf ); 34 } 35 ----------------------------------------------------------------36 /* виртуальн1й */ string:: ~string( void ) 37 {
63 { 64 65 } 66 67 /* 68 { 69 70 } 71 73 { 74 75 } 76 77 inline ostream &operator<<( ostream &output, const string &s ) 78 { 79 Эта функция не является функцией-членом класса string, 8 0 но не должна быть дружественной, потому что мной тут 81 реализован метод вывода строкой своего значения. 83 s.print(output); 84 return output; 85 } Вы заметите, что я умышленно не реализовал следующую функцию в листинге 7: string::operator const char*() { return buf; } Если бы реализовал, то мог бы сделать следующее: з delete buf; 39 } 40 ----------------------------------------------------------------41 /* виртуальн1й */ const string &string::operator=( const string &r) 42 { 43 if( this != &r ) 44 { 45 if( length != r.length ) 46 { 47 free( buf ); 4 8 length = r.length; 4 9 buf = new char[ length ]; 50 } 51 strcpy( buf, r.buf ); 52 } 53 return *this; 54 } 55 56 57 /* 58 { 59 60 } 61 Операция приведения вызывает функцию operator const char* возвращающую buf. Тем не менее, деструктор класса string передает этот буфер оператору delete, когда строка покидает область действия. Следовательно, функция g() возвращает указатель на освобожденную память. В отличие от предыдущего примера, при этой второй проблеме нет закрученного оператора приведения в два этапа, намекающего нам, что что-то не так. Реализация в листинге 7 исправляет это, заменив преобразование void f( void ) string s; ... printf( %s\n , (const char*)s ); но я не смогу реализовать функцию operator char*(), которая бы работала со строкой Unicode, использующей для символа 16-бит. Я должен бы был написать функцию operator wchar t*(), тем самым модифицировав код в функции f(): printf( %s/n , (const wchar t*)s ); Тем не менее, одним из главных случаев, которых я стараюсь избежать при помощи объектно-ориентированного подхода, является необходимость модификации пользователя объекта при изменении внутреннего определения этого объекта, поэтому преобразование в char* неприемлемо. Также есть проблемы со стороны внутренней согласованности. Имея указатель на buf, возвращенный функцией operator const char*(), вы все же можете модифицировать строку при помощи указателя и испортить поле length, хотя для этого вам придется немного постараться: string s; ... char *p = (char *)(const char *)s; gets( p ); В равной степени серьезная, но труднее обнаруживаемая проблема возникает в следующем коде: const char *g( void ) string s; ... return (const char *)s;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |