Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VC++(теория).doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
375.3 Кб
Скачать

Дружественные функции и классы

  • "Друзья" класса, или "дружественные" (friend) функции и классы - имеют доступ к защищенным данным данного класса. Они могут использовать недоступную извне информацию класса, не являясь членами данного класса.

class time_class {

long secs; // Защищенное данное класса

friend long present_time(time_class); // Дружественная функция

public:

time_class(char*); // Конструктор класса

};

time_class::time_class(char *tm) // Реализация конструктора

{

;

}

long present_time(time_class tz) // Реализация внешней дружественной функции

{

long seconds_total = tz.secs; // Доступ к защищенному данному класса

return seconds_total;

}

Указатель this

  • Указатель this указывает на текущий объект, к данным которого обращаются. Обычно его не используют, опуская, подобно использованию Me в Visual Basic. Как правило, его используют, в связанных списках, т.е. когда необходимо передать указатель на самого себя (объекта, чья функция вызывается) другому объекту

class class_name {

char chr; // Данное класса

public:

void begin_conv(char k) // Функция класса

{ chr = k; } // Первый метод обращения к данным класса

char conv_char(void)

{ return (this->chr); } // Второй метод – через указатель на себя

class_name* pushself(void) // Функция класса, возвращающая указатель

{ return (this); } // на созданный объект

};

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

  • Кроме перегрузки методов в С++ можно перегружать и такие привычные операции, как (*, /, -, +)

  • Перегружаемые операции:

+ - * / = < > += -=

+= /= << >> >>= <<= == != <=

>= ++ -- % & ^^ ! | ~

&= ^= |= && || %= [] ()

new delete

  • Ограничения:

  • синтаксис и приоритет операции не должны отличаться от первоначально определенных

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

  • Синтаксис

тип operator операция (список параметров)

  • Пример перегрузки операции сложения (\31OPOVER)

class angle { // Класс для оперирования углами

int degrees, minutes, seconds; // Защищенные данные класса

public:

angle() // Конструктор по умолчанию

{ degrees=0; minutes=0; seconds=0;}

angle(int d, int m, int s) // Второй конструктор

{ degrees=d; minutes=m; seconds=s;}

angle operator+(angle); // Перегруженная операция сложения

void info_display(void); // Функция для вывода информации об угле

};

angle angle::operator+(angle ang_sum)

{

angle ang; // Промежуточная переменная для вычислений

// Логика операции сложения углов в градусах, минутах и секундах

ang.seconds = (seconds + ang_sum.seconds) % 60;

ang.minutes = ((seconds + ang_sum.seconds) / 60 +

minutes + ang_sum.minutes) % 60;

ang.degrees = ((seconds + ang_sum.seconds) / 60 +

minutes + ang_sum.minutes) / 60;

ang.degrees += degrees + ang_sum.degrees;

return ang; // Возврат значения операции

}

void angle::info_display(void)

{

cout << "The value of angles is " << degrees << "° "

<< minutes << "' " << seconds << "\"" << endl;

}

int main()

{

angle angle1(37, 15, 56); // Создание объектов класса угла

angle angle2(75, 17, 57);

angle angle3(10, 44, 44);

angle sum_of_angles;

// Использование перегруженной операции сложения

sum_of_angles = angle1 + angle2 + angle3;

sum_of_angles.info_display(); // Вывод результата сложения углов

return(0);

}

Задание: Перегрузить операцию вычитания углов для класса угла и проверить ее действие. Формулы расчета приведены в модуле после функции main() в комментариях.

Производные классы и виртуальные функции

  • Производные классы можно рассматривать как расширение существующего класса.

  • Имея один родительский класс, можно использовать единый интерфейс для получения нескольких производных классов.

  • Любой класс С++ может быть родительским, и любой производный класс будет следовать его описанию.

  • Класс-потомок может иметь дополнительные свойства по сравнению с базовым классом

  • В потомке можно изменить права доступа к данным, добавить новые элементы или перегрузить имеющиеся методы (использование виртуальных методов)

  • Синтаксис

class тип_потомка : [public|private|protected] предок {

....

}

  • Виртуальная функция - функция которая может быть переопределена в производных классах

  • Вызывая виртуальный метод базового класса для переменной типа указателя на предка (которая может содержать и указатель на потомка), автоматически вызывается метод потомка.

  • Если после определения виртуальной функции класса стоит = 0 , то эта функция обязана быть переписана в производных классах и экземпляр данного базового класса создать нельзя (\32VIRT)

class Account { // Абстрактный базовый класс счета

protected: // Данные в разделе protected доступны потомкам

double balance; // Переменная баланса счета

public:

Account( double d ) // Инициализирующий конструктор

{ balance = d; }

virtual double GetBalance() // Функция получения баланса счета

{ return balance; }

virtual void PrintBalance() = 0; // Абстрактная функция печати баланса

};

class CheckingAccount : public Account { // Производный класс чекового счета

public:

CheckingAccount(double d) : Account(d) // Конструктор,вызывающий конструктор предка

{ }

double GetBalance() // Переопределение виртуальной функции

{ return (balance * 0.8); } // Логика расчета баланса для чекового счета

void PrintBalance(); // Переопределение виртуальной функции

};

class SavingsAccount : public Account // Производный класс сберегательного счета

{

double savings_percent; // Расширение базового класса

public:

SavingsAccount(double d) : Account(d) // Конструктор, вызывающий конструктор предка

{ savings_percent = 0.01; } // и инициализирующий свои данные

void PrintBalance(); // Переопределение виртуальной функции

};

void CheckingAccount::PrintBalance() // Реализация виртуальной функции печати

{ // Вывод информации о балансе чекового счета

cout << endl << "Checking account balance: " << GetBalance() << endl ;

}

void SavingsAccount::PrintBalance() // Реализация виртуальной функции печати

{ // Вывод информации о балансе сберегательного счета

cout << endl << "Savings account balance: " << GetBalance() << endl;

}

int main()

{

// Динамическое создание объектов классов CheckingAccount и SavingsAccount.

CheckingAccount *pChecking = new CheckingAccount( 1000.00 );

SavingsAccount *pSavings = new SavingsAccount( 1000.00 );

Account *pAccount; // Объявление переменной-указателя на базовый класс счета

pAccount= pChecking; // Заставляем переменную ссылаться на объект класса-потомка

pAccount->PrintBalance();// Вызовется функция печати баланса чекового счета

pAccount = pSavings; // Переменная ссылается на объект класса SavingsAccount

pAccount->PrintBalance();// Вызовется функция класса SavingsAccount

return(0);

}

Задание: Переопределить виртуальную функцию GetBalance() для класса SavingsAccount, в которой рассчитать баланс как текущий баланс плюс процент: (balance*(1+savings_percent))

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