Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа ЯПВУ.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆

Перегрузка функций

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

int abs(int x);

double abs(double x);

Полиморфизм

В переводе с греческого polymorphos – многообразный. Если один и тот же объект может по‑разному использоваться, в зависимости от обстоятельств, то он обладает полиморфизмом.

Если базовый класс Base содержит виртуальную (virtual) функцию vf, а производный класс Derived также содержит функцию vf, то вызов vf для объекта класса Derived вызывает Derived:: vf:

struct Base {

virtual void vf(); // виртуальная функция

void f();

};

struct Derived : public Base {

void vf();

void f();

};

void main() {

Derived d;

Base* ptr = &d; // Derived унаследован от Base

ptr->vf(); // Будет вызвана функция Derived::vf()

ptr->f(); // Будет вызвана функция Base::f()

}

Из этого следует, что тип объектов классов с виртуальными функциями и объектов классов, выведенных из таких классов, могут быть определены во время выполнения.

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

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

Функции-друзья

Другом класса является функция не являющаяся элементом класса, которая может использовать имена закрытых членов – такая функция должна быть описана с модификатором friend. Следующий пример иллюстрирует различия между членами и друзьями:

class A {

int value;

friend void friend_set(A* pr, int v);

public:

void member_set(int v);

};

void friend_set(A* ptr, int v) { ptr->value = v;

void A::member_set(int v) { value = v; }

void main() {

A obj;

friend_set(&obj, 10);

obj.member_set(10);

}

В отличии от функции – методов класса, функции-друзья не получают неявную ссылку-указатель на объект, поэтому это необходимо делать явно, и соответственно this использовать нельзя.

Абстрактные классы

Виртуальная функция может быть описана как «чистая» виртуальная функция с помощью добавления модификатора '=0':

class AbstractBase {

public: virtual void fn() = 0;

}

Это означает, что тело данной функции в классе AbstractBase не определено. Классы-потомки обязаны реализовать данную функцию. Нельзя создавать экземпляры класса AbstractBase – он является абстрактным, но можно создавать указатели на класс.

Абстрактные классы в C++ реализуют идею создания интерфейсов – классов, которые определяют («декларируют») поведение (выполняемые операции) для всех классов-потомков расширяющих абстрактный класс (реализующих интерфейс), например:

// Интерфейс для классов, которые могут печатать сами себя

class Printable {

public: virtual void print() = 0;

};

// Реализация 1 интерфейса

struct Person : public Printable {

char *name;

void print() { cout << “Имя : ” << name << endl; }

};

// Реализация 2 интерфейса

struct Material : public Printable {

int weight;

void print() { cout << “Масса = ” << weight << endl; }

};

void main () {

Person man; man.name = “Adam”;

Material mat; mat.weight = 128;

Printable *p1, *p2;

p1 = &man; p2 = &mat;

p1->print(); // Имя : Adam

p2->print(); // Масса = 128

}