
- •220300 - Системы автоматизированного проектирования
- •Тема 2. Технологии программирования
- •Тема 2. Технология разработки крупных приложений
- •Структуры
- •Структуры и функции
- •Массивы структур
- •Поиск в массиве структур
- •Вложенность структур
- •Рекурсия
- •Алгоритм быстрой сортировки
- •Массивы структур и бинарные файлы
- •Динамические структуры данных
- •Линейные списки
- •Очереди
- •Контрольная работа
- •Объектно-ориентированное программирование. Классы
- •Конструкторы
- •Перегруженные конструкторы
- •Определение методов класса вне класса
- •Объекты, возвращаемые функцией (методом)
- •Структуры и классы
- •Классы и память
- •Статические данные класса
- •Константные методы
- •Деструкторы
- •Массивы и классы
- •Массивы объектов
- •Строки Строковый тип или стандартный класс string
- •Тип строк AnsiString
- •Перегрузка операций
- •Перегрузка арифметических операций
- •Перегрузка операций сравнения
- •Перегрузка операции приведения типа
- •Преобразования объектов в основные типы и наоборот
- •Преобразование объектов классов в объекты других классов
- •Наследование
- •Конструкторы производного класса
- •Перегрузка функций
- •Иерархия классов
- •Общее и частное наследование. Комбинации доступа
- •Множественное наследование
- •Включение. Классы в классах
- •Виртуальные и дружественные функции
- •Абстрактные классы и чистые виртуальные функции
- •Виртуальные деструкторы
- •Виртуальные базовые классы или устранение неоднозначности при множественном наследовании
- •Дружественные функции
- •Дружественные классы
- •Указатель this
- •Многофайловые программы
- •Распознавание нажатых клавиш
Тип строк 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 не играет роли аргумента и не означает целое число. Это просто сигнал для компилятора, чтобы использовалась постфиксная версия операции инкрементирования.