Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Otvety_YaSiTP_III_attesattsia_II_semestr.docx
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
74.37 Кб
Скачать

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 и названия операции. Во всём остальном этот метод определяется как и любые другие.

Использовать перегруженные операции с пользовательскими типами очень просто - так же как и с обычными типами данных.

    1. Перегрузка постфиксных операций.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]