Курс лекций мдк 01. 02 «Прикладное программирование» пм 01 «Разработка программных модулей программного обеспечения для компьютерных систем»



Download 350,99 Kb.
bet14/22
Sana08.12.2022
Hajmi350,99 Kb.
#881790
TuriКурс лекций
1   ...   10   11   12   13   14   15   16   17   ...   22
Bog'liq
lektsii pm01-1

Дружественность не наследуется. Если A объявляет класс

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





    • Дружественность не распространяется на потомков.

Если класс A объявляет B другом, то B не становится автоматически другом для классов-потомков A. Каждый потомок, если это нужно, должен объявить B своим другом самостоятельно.


При разработке программ случается, что одних функций-методов для доступа к личным полям не хватает. Это не обязательно признак просчета


28

при разработке классов, просто некоторые проблемы невозможно решить с помощью функций-членов. Например, что делать, если функции требуется полный доступ к полям двух классов?


Для того, чтобы в подобных случаях не приходилось делать поля публичными, С++ позволяет классу объявлять друзей (friends) - функции и классы, у которых есть полный доступ к начинке класса (такой же доступ, как у его собственных функций). Делается это с помощью ключевого слова friend. В приведенном ниже примере в классе A определяются friend-функция print_fields(A a) и friend-класс B.



//

Forward

declaration




of




class

B;

class




























B;

//




class










A







definition

class













A













{

int













n1,













n2;

friend




void







print_fields(A




a);

friend













class










B;

public:































set_fields(n_1,n_2)






















{

n1













=













n_1;

n2













=













n_2;

}































};































void




print_fields(A







a)




{

cout

<<

a.n1

<<

"

"

<<

a.n2

<<

endl;

}































Функция print_fields(A a) имеет полный доступ к личным полям класса A, поскольку она объявлена friend-функцией класса. Заметьте - friend-объявление распространяется только на функцию с указанной сигнатурой, в нашем случае print_fields(A), а не на все функции с именем print_fields. Что касается объявления


friend class B;

то оно делает поля класса A доступными для всех функций-членов класса B.


Функции и классы-друзья незаменимы там, где разные типы данных тесно связаны между собой, но реализовывать их в одном классе невыгодно или просто невозможно. Хороший пример этому - С++-стиль ввода-вывода, в котором именно дружественные функции позволяют разрабатывать версии операторов << и >> для вновь создаваемых классов.


29


Тема «Перегрузка операций (операторов) для классов. Функции-операции. Бинарные операции. Унарные операции»
Перегрузка - это возможность поддерживать несколько функций с одним названием, но разными сигнатурами вызова. Рассмотрим пример:

double sqrt ( double x ); //Функция корня для чисел с плавающей точкой int sqrt ( int x ); //Функция корня для целых чисел


...

sqrt(1.5);//В этом случае вызовется функция чисел с плавающей точкой sqrt(7);//А в этом уже для целых чисел

Компилятор сам определяет какую функцию выбрать в зависимости от сигнатуры. Более подробно о том, как компилятор определяет какую из перегруженных функций выбрать, можно прочесть в стандарте языка С++.


Пример операторов:


+, <<, & и т.д.


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




Список операторов:



  • - * / % //Арифметические операторы

+= -= *= /= %=
+a -a //Операторы знака

++a a++ --a a-- //Префиксный и постфиксный инкременты && || ! //Логические операторы


& | ~ ^ &= |= ^=




<< >> <<= >>= //Битовый сдвиг = //Оператор присваивания == != //Операторы сравнения


< > >= <=

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


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


30

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


#include

using namespace std;


//Класс для реализации комплексных чисел:
class MComp{
public:
double Re;

double Im;


//Переопределение оператора сложения методом класса:
MComp operator+(MComp y){
MComp z;
z.Re=Re+y.Re;

z.Im=Im+y.Im;


return z;}
};
int main(){
MComp a,b,c;

a.Re=1;
a.Im=2;


b.Re=2;
b.Im=3;
//Сложение объектов:

c=a+b;
cout << "c.Re = " << c.Re << "\n";


cout << "c.Im = " << c.Im << "\n";
return 0;
}


Тема «Полиморфизм и виртуальные функции»

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


Для обеспечения абстракции данных необходимо связать несколько классов в иерархию наследования и назначить функциям одинаковые спецификации. Например:


class Figure


{
void Draw() const;

};


class Square : public Figure
{
void Draw() const;

};
31


class Circle : public Figure

{
void Draw() const;


};

class Window


{
void Draw() const;


};



  • результате компиляции этих определений формируется шесть тел функций. В коде они используются одинаково; выбор конкретного экземпляра функции осуществляется в зависимости от типа экземпляра объекта, для которого осуществляется вызов. Согласованность поведения функций остаётся на совести программиста.

Circle *c = new Circle(0,0,5);


Figure *f = c; // правильно: Figure — базовый класс для Circle c->Draw();


f->Draw(); // Указатели равны друг другу, но для f и c будут вызваны разные функции


SquareWindow *sw = new Window(0,0,5);

sw->Draw(); // используется так же


f = sw; // ошибка! SquareWindow не входит в число наследников Figure!

Как видно, диапазон этого вида полиморфизма в С++ ограничивается на этапе проектирования заданным перечнем типов. По умолчанию такой полиморфизм является статическим, но при использовании спецификатора virtual он превращается в динамический:


class Figure


{...
virtual void Draw() const;
};

class Square : public Figure


{

void Draw() const;


};

class Circle : public Figure


{...
void Draw() const;
};

Figure* figures[10];


figures[0] = new Square(1, 2, 10);
figures[1] = new Circle(3, 5, 8);
...
for (int i = 0; i < 10; i++)
figures[i]->Draw();



  • этом случае для каждого элемента массива будет вызвана

Square::Draw() или Circle::Draw(), в зависимости от вида фигуры.




Чистой виртуальной функцией называется виртуальная функция-член, которая объявлена со спецификатором = 0 вместо тела:

class Figure



32

{
...


virtual void Draw() const = 0;


);

Чистая виртуальная функция не имеет определения и не может быть непосредственно вызвана. Цель объявления такой функции — создать в общем базовом классе сигнатуру-прототип, которая не имела бы собственного определения, но позволяла создавать такие определения в классах-потомках и вызывать их через указатель на общий базовый класс. Функция-метод объявляется чистой виртуальной тогда, когда её определение для базового класса не имеет смысла.


Так, в вышеприведённом примере для базового класса Figure определение функции Draw() не имеет смысла, так как «фигур вообще» не бывает и их невозможно отобразить, но описание такой функции необходимо, чтобы можно было её переопределить в классах-потомках и вызывать методы Draw этих классов через указатель на Figure. Следовательно, вполне логично объявить Figure.Draw() как чистую виртуальную функцию-метод.





  • понятием чистой виртуальной функции в C++ тесно связано понятие «абстрактный класс». Абстрактным классом называется такой, у которого есть хотя бы одна не переопределённая чистая виртуальная функция-метод. Экземпляры таких классов создавать запрещено, абстрактные классы могут использоваться только для порождения новых классов путём наследования. Если в классе-потомке абстрактного класса не переопределены все унаследованные чистые виртуальные функции, то такой класс также является абстрактным и на него распространяются все указанные ограничения.




Download 350,99 Kb.

Do'stlaringiz bilan baham:
1   ...   10   11   12   13   14   15   16   17   ...   22




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish