Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






  • Как продвинуть сайт на первые места?
    Вы создали или только планируете создать свой сайт, но не знаете, как продвигать? Продвижение сайта – это не просто процесс, а целый комплекс мероприятий, направленных на увеличение его посещаемости и повышение его позиций в поисковых системах.
    Ускорение продвижения
    Если вам трудно попасть на первые места в поиске самостоятельно, попробуйте технологию Буст, она ускоряет продвижение в десятки раз, а первые результаты появляются уже в течение первых 7 дней. Если ни один запрос у вас не продвинется в Топ10 за месяц, то в SeoHammer за бустер вернут деньги.
    Начать продвижение сайта
  • Листинг 12.12. Использование класса String






    1: // Листинг. 12.12

    2:

    3: #include < iostream.h>

    4: #include < string.h>

    5:

    6: // Рудиментарный класс string

    7: class String

    8: {

    9: public:

    10: // Конструкторы

    11: String()

    12: Stnng(const char *const),

    13: Stnng(const String &),

    14: ~Stnng()

    15:

    16: // Перегруженные операторы

    17: char & operator[](unsigned short offset),

    18: char operator[](unsigned short offset) const,

    19: Stnng operator+(const String&),

    20: void operator+=(const String&)

    21: Stnng & operator= (const Stnng &),

    22:

    23: // Основные методы доступа

    24: unsigned short GetLen()const { return itsLen, }

    25: const char * GetStnng() const { return itsStnng, }

    26:

    27: private:

    28: Stnng (unsigned short), // Закрытый конструктор

    29: char * itsStnng,

    30: unsigned short itsLen

    31: }

    32:

    33: // Конструктор, заданный no умолчанию, создает строку нулевой длины

    34: String String()

    35: {

    36: itsStnng = new char[1]

    37: itsStrmg[0] = '\0'

    38: itsLen=0;

    39: }

    40:

    41: // Закрытый (вспомогательный) конструктор

    42: // используется только методами класса для создания

    43: // строк требуемой длины с нулевым наполнением

    4й: String String(unsigned short len)

    45: {

    46: itsStnng = new char[len+1]

    47: for (unsigned short i = 0 i< =len, i++)

    48: itsString[i] = \0,

    49: itsLen=len,

    50: }

    51:

    52: // Преобразование массива символов в строку

    53: String String(const char * const cString)

    54: {

    55: itsLen = strlen(cString);

    56: itsString = new char[itsLen+1];

    57: for (unsigned short i = 0; i< itsLen: i++)

    58: itsString[i] = cString[i];

    59: itsString[itsLen]='\0';

    60: }

    61:

    62: // Конструктор-копировщик

    63: String:: String (const String & rhs)

    64: {

    65: itsLen=rhs.GetLen();

    66: itsString = new char[itsLen+1];

    67: for (unsigned short i = 0; i< itsLen; i++)

    68: itsString[i] = rhs[i];

    69: itsString[itsLen] = '\0';

    70: }

    71:

    72: // Деструктор для освобождения памяти

    73: String:: ~String ()

    74: {

    75: delete [] itsString;

    76: itsLen = 0;

    77: }

    78:

    79: // Оператор присваивания освобождает память

    80: // и копирует туда string и size

    81: String& String:: operator=(const String & rhs)

    82: {

    83: if (this == & rhs)

    84: return *this;

    85: delete [] itsString;

    86: itsLen=rhs.GetLen();

    87: itsString = new char[itsLen+1];

    88: for (unsigned short i = 0; i< itsLen; i++)

    89: itsString[i] = rhs[i];

    90: itsString[itsLen] = '\0';

    91: return *this;

    92: }

    93:

    94: //неконстантный оператор индексирования

    95: // возвращает ссылку на символ так, что его

    96: // можно изменить!

    97: char & String:: operator[](unsigned short offset)

    98: {

    99: if (offset > itsLen)

    100: return itsString[itsLen-1];

    101: else

    102: return itsString[offset];

    103: }

    104:

    105: // константный оператор индексирования для использования

    106: // с константными объектами (см. конструктор-копировщик!)

    107: char String:: operator[](unsigned short offset) const

    108: {

    109: if (offset > itsLen)

    110: return itsString[itsLen-1];

    111: else

    112: return itsString[offset];

    113: }

    114:

    115: // создание новой строки путем добавления

    116: // текущей строки к rhs

    117: String String:: operator+(const String& rhs)

    118: {

    119: unsigned short totalLen = itsLen + rhs.GetLen();

    120: String temp(totalLen);

    121: unsigned short i;

    122: for (i= 0; i< itsLen; i++)

    123: temp[i] = itsString[i];

    124: for (unsigned short j = 0; j< rhs.GetLen(); j++, i++)

    125: temp[i] = rhs[j];

    126: temp[totalLen]='\0';

    127: return temp;

    128: }

    129:

    130: // изменяет текущую строку и возвращает void

    131: void String:: operator+=(const String& rhs)

    132: {

    133: unsigned short rhsLen = rhs.GetLen();

    134: unsigned short totalLen = itsLen + rhsLen;

    135: String temp(totalLen);

    136: unsigned short i;

    137: for (i = 0; i< itsLen; i++)

    138: temp[i] = itsString[i];

    139: for (unsigned short j = 0; j< rhs.GetLen(); j++, i++)

    140: temp[i] = rhs[i-itsLen];

    141: temp[totalLen]='\0';

    142: *this = temp;

    143: }

    144:

    145: int main()

    146: {

    147: String s1(" initial test");

    148: cout < < " S1: \t" < < s1.GetString() < < endl;

    149:

    150: char * temp = " Hello World";

    151: s1 = temp;

    152: cout < < " S1: \t" < < s1.GetString() < < endl;

    153:

    154: char tempTwo[20];

    155: strcpy(tempTwo, "; nice to be here! ");

    156: s1 += tempTwo;

    157: cout < < " tempTwo: \t" < < tempTwo < < endl;

    158: cout < < " S1: \t" < < s1.GetString() < < endl;

    159:

    160: cout < < " S1[4]: \t" < < s1[4] < < endl;

    161: s1[4]='o';

    162: cout < < " S1: \t" < < s1.GetString() < < endl;

    163:

    164: cout < < " S1[999]: \t" < < s1[999] < < endl;

    165:

    166: String s2(" Another string");

    167: String s3;

    168: s3 = s1+s2;

    169: cout < < " S3: \t" < < s3.GetString() < < endl:

    170:

    171: String s4;

    172: s4 = " Why does this work? ";

    173: cout < < " S4: \t" < < s4.GetString() < < endl;

    174: return 0;

    175: }

     

    Результат:

    S1: initial test

    S1: Hello world

    tempTwo:; nice to be here!

    S1: Hello world; nice to be here!

    S1[4]: o

    S1: Hello World; nice to be here!

    S1[999]:!

    S3: Hello World; nice to be here! Another string

    S4: Why does this work?

     

    Анализ: В строках 7—31 объявляется простой класс String. В строках 11—13 объявляются конструктор по умолчанию, конструктор-копировщик и конструктор для приема существующей строки с концевым нулевым символом (стиль языка С).

    В классе String перегружаются операторы индексирования ([]), суммирования (+) и присваивания с суммой (+=). Оператор индексирования перегружается дважды. Один раз как константная функция, возвращающая значение типа char, а другой — как неконстантная функция, возвращающая указатель на char.

    Неконстантная версия оператора используется в выражениях вроде строки 161: SomeString[4]=V;

    В результате открывается прямой доступ к любому символу строки. Поскольку возвращается ссылка на символ, функция получает доступ к символу и может изменить его.

    Константная версия оператора используется в тех случаях, когда необходимо получить доступ к константному объекту класса String, например при выполнении конструктора-копировщика в строке 63. Обратите внимание, что в этом случае открывается доступ к rhs[i], хотя rhs был объявлен как const String &. К этому объекту невозможно получить доступ, используя неконстантные функции-члены. Поэтому оператор индексирования необходимо перегрузить как константный.

    Если возвращаемый объект окажется слишком большим, возможно, вам потребуется установить возврат не значения, а константной ссылки на объект. Но поскольку в нашем случае один символ занимает всего один байт, в этом нет необходимости.

    Конструктор, заданный по умолчанию, выполняется в строках 33—39. Он создает строку нулевой длины. Общепринято, что в классе String длина строки измеряется без учета концевого нулевого символа. Таким образом, строка, созданная по умолчанию, содержит только концевой нулевой символ.

    Конструктор-копировщик выполняется в строках 63—70. Он задает длину новой строки равной длине существующей строки плюс одна ячейка для концевого нулевого символа. Затем конструктор-копировщик копирует существующую строку в новую и добавляет в конце нулевой символ окончания строки.

    В строках 53—60 выполняется конструктор, принимающий строку с концевым нулевым символом. Этот конструктор подобен конструктору-копировщику. Длина существующей строки определяется с помощью стандартной функции strlen() из библиотеки String.

    В строке 28 объявляется еще один конструктор, String(unsigned short), как закрытая функция-член. Он был добавлен для того, чтобы не допустить создания в классе String строк произвольной длины каким-нибудь другим пользовательским классом. Этот конструктор позволяет создавать строки только внутри класса String в соответствии со сделанными установками, как, например, в строке 131 с помощью operator+=. Более подробно этот вопрос рассматривается ниже, при объявлении operator+=.

    Конструктор String(unsigned short) заполняет все элементы своего массива символов значениями NULL. Поэтому в цикле for выполняется проверка i< =len, а не i< len.

    Деструктор, выполняемый в строках 73—77, удаляет строку текста, поддерживаемую классом String. Обратите внимание, что за оператором delete следуют квадратные скобки. Если опустить их, то из памяти компьютера будут удалены не все объекты класса, а только первый из них.

    Оператор присваивания прежде всего определяет, не соответствуют ли друг другу операнды слева и справа. Если операнды отличаются друг от друга, то текущая строка удаляется, а новая копируется в эту область памяти. Чтобы упростить присвоение, возвращается ссылка на строку, как в следующем примере:

    String1 = String2 = String3;

    Оператор индексирования перегружается дважды. В обоих случаях проверяются границы массива. Если пользователь попытается возвратить значение из ячейки памяти, находяшейся за пределами массива, будет возвращен последний символ массива (len-1).

    В строках 117-128 оператор суммирования (+) выполняется как оператор конкатенации. Поэтому допускается создание новой строки из двух строк, как в следующем выражении:

    String3 = String1 + String2;

    Оператор (+) вычисляет длину новой строки и сохраняет ее во временной строке temp. Эта процедура вовлекает закрытый конструктор, который принимает целочисленный параметр и создает строку, заполненную значениями NULL. Нулевые значения затем замещаются символами двух строк. Первой копируется строка левого операнда (*this), после чего — строка правого операнда (rhs).

    Первый цикл for последовательно добавляет в новую строку символы левой строки'. Второй цикл for выполняет ту же операцию с правой строкой. Обратите внимание, что счетчик i продолжает отсчет символов новой строки после того, как счетчик j начинает отсчет символов строки rhs.

    Оператор суммирования возвращает временную строку temp как значение, которое присваивается строке слева от оператора присваивания (string1). Оператор += манипулирует с уже существующими строками, как в случае string1 += string2. В этом примере оператор += действует так же, как оператор суммирования, но значение временной строки temp присваивается не новой, а текущей строке (*this = temp), как в строке 142.

    Функция main() (строки 145—175) выполняется для проверки результатов работы данного класса. В строке 147 создается объект String с помощью конструктора, задающего строки в стиле языка С с концевым нулевым символом. Строка 148 выводит содержимое этого объекта с помощью функции доступа GetString(). В строке 150 создается еще одна строка текста в стиле языка С. В строке 151 тестируется перегруженный оператор присваивания, а строка 152 выводит результат.

    В строке 154 создается третья строка с концевым нулевым символом — tempTwo. В строке 155 с помощью функции strcpy() происходит заполнение буфера строкой символов nice to be here!. В строке 156 с помощью перегруженного оператора += осуществляется конкатенация строки tempTwo к существующей строке s1. Результат выводится на экран в строке 158.

    В строке 160 возвращается и выводится на экран пятый символ строки — s1. Затем в строке 161 этот символ замещается другим с помощью неконстантного оператора индексирования ([]). Результат выводится строкой 162, чтобы показать, что символ строки действительно изменился.

    В строке 164 делается попытка получить доступ к символу за пределами массива. Возвращается и выводится на печать последний символ строки, как и было предусмотрено при перегрузке оператора индексирования.

    В строках 166 и 167 создаются два дополнительных объекта String, и в строке 168 используется перегруженный оператор суммирования. Результат выводится строкой 169.

    В строке 171 создается еще один объект класса String — s4. В строке 172 используется оператор присваивания, а строка 173 выводит результат. Оператор присваивания перегружен таким образом, чтобы использовать константную ссылку класса String, объявленную в строке 21, но в данном случае в функцию передается строка с концевым нулевым символом. Разве это допустимо?

    Хотя компилятор, ожидая получить объект String, вместо этого получает массив символов, он автоматически проверяет возможность преобразования полученного значения в ожидаемую строку. В строке 12 объявляется конструктор, который создает объект String из массива символов. Компилятор создает временный объект String из полученного массива символов и передает его в функцию оператора присваивания. Такой процесс называется неявным преобразованием. Если бы в программе не был объявлен соответствующий конструктор, преобразующий массивы символов, то для этой строки компилятор показал бы сообщение об ошибке.

     






    © 2023 :: MyLektsii.ru :: Мои Лекции
    Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
    Копирование текстов разрешено только с указанием индексируемой ссылки на источник.