Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по Технологии разработки ПО 2005.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
833.54 Кб
Скачать

Тип строк AnsiString

В С++Builder многие компоненты работают с типом строк AnsiString, объявленным в заголовочном файле vcl.h. Это строки с нулевым символом в конце. При объявлении переменные типа AnsiString инициализируются пустыми строками. Для AnsiString определены операции отношения ==, !=, >, <, >=, <= и операции +, =, +=. Сравнение происходит с учётом регистра. Определена также операция индексации []. Индексы начинаются с 1.

Тип AnsiString не рекомендуется использовать в консольных приложениях, поскольку он не перегружен для операций cin >> и cout <<. Он предназначен для визуального программирования. У этого типа имеются такие же методы как и у класса string (только пишутся с большой буквы). Перечислим основные методы класса AnsiString:

  • Insert(…str, int…) вставляет в вызывающую строку подстроку str на место, начинающиеся с индекса, указанного во втором аргументе;

  • Length() возвращают количество символов в строке;

  • AnsiCompare(str) сравнивает символы вызывающей строки со строкой, указанной в качестве аргумента. Возвращает 0 при равенстве строк;

  • AnsiCompareIC(str) осуществляет сравнение без учёта регистра;

  • AnsiPos(str) возвращает индекс первого символа первого вхождения подстроки str в вызывающей строке. Возвращает 0 при неудаче.

  • substr(позиция фрагмента , кол-во символов) возвращает фрагмент строки, для которой этот метод был вызван;

  • Delete(int, int) удаляет из вызывающей строки число символов, указанное во втором параметре, начиная с позиции, указанной в первом параметре;

  • SubString(int , int ) возвращает подстроку, начинающуюся с символа в позиции, указанной в первом аргументе, и содержащую количество символов, указанное во втором аргументе.

Преобразование строки AnsiString в строку типа char осуществляется с помощью функции c_str(), например:

AnsiString s1;

s1 = "Privet mir";

char *s2 = s1.c_str();

cout << s2;

Обратное преобразование выполняется с помощью функции AnsiString(char *s).

В заключение хочу отметить, что на практике несмотря на все преимущества типов string и AnsiString иногда бывают такие ситуации, когда гораздо удобнее работать с типом char.

Лекция 6 (10,5 стр.)

Перегрузка операций

Перегрузка операций – это одна из самых интересных возможностей ООП. Использование перегрузки операций может превратить сложный и малопонятный текст программы в интуитивно понятный. Например, не очень понятная строка d3=d1.plus(d2) может быть заменена на более читаемую и привычную d3=d1+d2 с помощью перегрузки операций. Такие операции, как +, -, *, /, <=, += и т.п., обычно работают только с основными типами данных. Для использования этих операций с определёнными программистом типами данных необходимо применять перегрузку.

Любая операция, определённая в С++ (за исключением :: , ?: , . , .* , #), может быть перегружена для созданного вами класса. Это делается с помощью операторных функций специального вида:

возвращаемый_тип operator знак_перегружаемой_операции (список параметров) { тело функции } .

Если операторная функция реализована как функция класса, то количество параметров у этой функции на единицу меньше, так как первым операндом при этом считается сам объект, вызвавший данную операцию !!!

Перегрузка подчиняется следующим правилам:

  • при перегрузке операций сохраняется количество аргументов, приоритеты операций и правила ассоциации, используемые в стандартных типах данных;

  • для стандартных типов данных переопределять операции нельзя;

  • операторные функции не могут иметь аргументов по умолчанию;

  • операторные функции наследуются (за исключением =);

  • операторные функции не могут определяться как static.

Рассмотрим пример перегрузки унарных операций. Создадим класс для хранения значения счётчика.

class Count {

private:

unsigned int c; // значение счетчика

public:

Count() { c = 0; } // конструктор

unsigned int get() { // метод: получить значение

return c;

}

void operator++() { // метод: увеличить значение

++c;

}

};

//---------------------------------------------------------------------------

int main( ) {

Count c1, c2; // определяем объекты

cout << "\nc1 = " << c1.get(); // выводим на экран (с1=0)

cout << "\nc2 = " << c2.get(); // выводим на экран (с2=0)

++c1; // увеличиваем c1

++c2; ++c2; // увеличиваем c2

cout << "\nc1 = " << c1.get(); // снова показываем значения (с1=1)

cout << "\nc2 = " << c2.get() << endl; // ñ2=2

getch(); return 0;

}

В данной программе в методе, увеличивающем значение объекта, использовано ключевое слово operator для перегрузки операции ++. В этом методе сначала указывается возвращаемый тип, затем ключевое слово operator, за которым стоит операция, которую мы перегружаем, а затем (список аргументов). Такой синтаксис говорит компилятору о том, что если операнд принадлежит классу Count, то нужно вызывать функцию с таким именем тогда, когда в программе встретится операция ++. Перегруженные операции компилятор отличает по типу данных их операндов. Это означает, что если в программе используется какая то переменная целого типа (int var; ++var;), то для её инкрементирования компилятор использует встроенную процедуру увеличения, а если унарная операция увеличения применяется к объекту, то компилятор вызовет функцию программиста.

Обратите внимание на то, что в методе void operator++( ) нет аргументов в связи с тем, что методы класса всегда имеют доступ к объектам класса, для которых они были вызваны.

Вопрос:

Как надо изменить метод void operator++( ), чтобы появилась возможность использовать строку с1=++с2 ?

Count operator++() {

++c; Count temp; temp.c=c;

return temp;

}

};

//---------------------------------------------------------------------------

int main( ) {

Count c1, c2;

++c1;

++c2; ++c2;

c1 = ++c2;

cout << "\nc1 = " << c1.get(); // ñ1=3

cout << "\nc2 = " << c2.get() << endl; // ñ2=3

getch(); return 0;

}

Здесь мы создаём новый временный объект класса для использования его в качестве возвращаемого значения. В данном методе единственной целью объекта temp является хранение возвращаемого значения для операции ++.

Рассмотрим 2-ой вариант решения этой задачи:

Count(int t) { c = t; }

Count operator++() { // метод: увеличить значение

++c;

return Count(c); // или return c;

}

};

//---------------------------------------------------------------------------

int main( ) {

}

Здесь, в строке return Count(c); происходят все те же действия, которые в предыдущем варианте занимали три строки. Здесь создаётся объект типа Count, который не имеет имени и инициализируется значением, полученным в виде параметра c. Чтобы этот метод работал, мы создали дополнительно конструктор с одним аргументом, способствующий возвращению функцией объекта, инициализированного значением c.

Рассмотрим пример перегрузки постфиксной записи, где переменная увеличивается после того, как её значение было использовано в выражении. Определим два варианта перегрузки операции ++.

class Count {

Count operator++() {

++c;

return Count(c); // èëè return c;

}

Count operator++(int) {

c++;

return Count(c); // èëè return c;

}

};

//---------------------------------------------------------------------------

int main( ) {

Count c1, c2, c3;

++c1;

++c2; ++c2;

c1 = ++c2;

c3++;

cout << "\nc1 = " << c1.get(); // ñ1=3

cout << "\nc2 = " << c2.get() << endl; // ñ2=3

cout << "\nc3 = " << c3.get() << endl; // ñ3=1

getch(); return 0;

}

Для реализации постфиксной записи операции ++ используется функция Count operator++(int), в которой int не играет роли аргумента и не означает целое число. Это просто сигнал для компилятора, чтобы использовалась постфиксная версия операции инкрементирования.