- •Классы. Принцип полиморфизма. Перегрузка методов в классах-наследниках.
- •2. Статическое и динамическое связывание имени метода с именем класса.
- •3. Реализация статического и динамического связывания. Виртуальные методы.
- •4.Перегрузка операций в классах. Перегрузка унарных операций.
- •Инкремент: При использовании данной операции над базовыми типами, к переменной можно прибавить или отнять единицу.
- •Перегрузка постфиксных операций.
- •Перегрузка бинарных операцій.
- •6. Форматный и бесформатный вывод. Методы форматирования и манипуляторы форматирования.
- •7. Манипуляторы. Манипуляторы с параметрами и без параметров.
- •8. Консольные потоки, в т.Ч. Стандартные.
- •9. Файловые и строковые потоки.
3. Реализация статического и динамического связывания. Виртуальные методы.
Статическое связывание может быть выполнено различными способами:
Во-первых, объект производного класса может обратиться к методу базового класса путем использования полного квалифицированного имени метода: имя_объекта.имя_базового_класса:: имя_метода
Во-вторых, при использовании для доступа к объектам производного типа переменных-указателей можно выполнять явное преобразование типа указателя:
(( имя_базового_класса*) имя_указателя)-> имя_метода
Любой объект некоторого класса представляет собой структуру, содержащую:
экземпляры собственных полей этого класса и полей его базового класса;
ссылки на собственные и унаследованные методы класса;
Если метод базового класса переопределяется в производном, то соответствующая ссылка структуре объекта также изменяется. При наличии виртуальных методов в структуру каждого объекта добавляется еще один элемент – ссылка на таблицу виртуальных методов. Эта таблица содержит адреса точек входа для всех методов, объявленных как виртуальные.
В результате присваивания указателю базового класса значения указателя производного класса передается не адрес объекта производного класса, а адрес его таблицы виртуальных методов (ТВМ).
Пример истользования виртуальных функция в программе-каталоге домашних животных: #include <iostream.h>
struct Pet // Базовый класс
{
char *name;
virtual void speak()=0;
Pet(char *nm)
{
name=nm;
}
};
struct Dog:public Pet
{
virtual void speak()
{
cout<<name<<“ говорит“”<<“ гав”<<endl;};
Dog(char *nm):Pet(nm){};
};
struct Cat:public Pet
{
virtual void speak()
{cout<<name<<“ говорит “<<“ Мяу”<<endl;}
Cat(char *nm):Pet(nm){};
}
};
int main()
{
Pet *mypets[]={new Dog(“Шарик”), new Cat(“Рыжик”), new Dog(“Тузик“)}; // Формируем массив
const int sz=sizeof(mypets)/sizeof(mypets[0]);
for(int k=0: k<sz; k++)
mypets[k]->speak();
return 0;
}
4.Перегрузка операций в классах. Перегрузка унарных операций.
Инкремент: При использовании данной операции над базовыми типами, к переменной можно прибавить или отнять единицу.
int a=1;
++a; // a = 2;
--a; // a = 1;
Использование преинкремента в классе Counter.
class Counter
{
private:
counter;
public:
Counter() : counter(0) {}
void operator++ ()
{
counter += 1;
//Можно также counter++ или ++counter
//это не имеет значения в данном случае
}
};
Counter a;
++a;
++a;
++a;
При использовании операции ++ (важно чтобы этот знак находился до идентификатора!) над объектом класса Counter, происходит увеличение переменной counter объекта a.
В данном примере мы перегрузили операцию ++. Делается это созданием метода внутри класса. Единственная важная особенность данного метода - имя идентификатора. Имя идентификатора для перегруженных операций состоит из ключевого слова operator и названия операции. Во всём остальном этот метод определяется как и любые другие.
Использовать перегруженные операции с пользовательскими типами очень просто - так же как и с обычными типами данных.
Перегрузка постфиксных операций.
