Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lutsik_Yu_A_Obektno_orientir_programmir_na_yaz.pdf
Скачиваний:
64
Добавлен:
11.05.2015
Размер:
4.33 Mб
Скачать

friend классу В, то это не означает, что В также является friend классу А), ни транзитивным (т.е. если A friend B и B friend C, то не следует, что A friend C);

- друзьями класса можно определить перегруженные функции. Каждая перегруженная функция, используемая как friend для некоторого класса, должна быть явно объявлена в классе со спецификатором friend.

3.8. Вложенные классы

Один класс может быть объявлен в другом классе, в этом случае внутрен- ний класс называется вложенным:

 

class ext_class

 

 

 

 

 

 

 

{ class int_cls

 

 

 

 

 

Р

 

{

∙ ∙

 

 

 

 

 

 

 

};

 

 

 

 

 

 

У

 

 

 

public:

 

 

 

 

 

И

 

};

 

∙ ∙

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Класс int_class является вложенным по отношению к классу ext_class

(внешний).

 

 

 

 

 

 

Г

 

 

 

 

 

 

 

 

 

 

 

а

 

 

Доступ к компонентам вложенного класса, имеющим атрибут private,

возможен только из функций вложенного клБсса и из функций внешнего клас-

са, объявленных со спецификатором friend во вложенном классе.

 

#include <iostream>

е

 

 

 

 

к

 

 

 

 

 

 

 

т

 

 

 

 

 

using namespace std;

 

 

внешний класс

 

 

class cls1

 

о

 

//

 

 

{ class cls2

 

//

вложенный класс

 

 

 

 

 

 

 

{

 

int b;

 

 

 

 

// все компоненты private для cls1 и cls2

 

 

 

cls2(int bb) : b(bb){}

// конструктор класса cls2

 

 

л

 

 

 

 

 

 

 

 

};

 

 

 

 

 

 

 

 

 

 

б

 

 

 

 

 

 

 

 

 

public:и

 

 

// public секция для cls1

 

 

int a;

 

 

 

 

 

 

 

 

и

 

 

 

 

 

 

//

вложенный класс

 

Б

class cls3

 

 

 

 

 

{

 

int c;

 

 

// private для cls1 и cls3

 

 

 

public:

 

 

// public-секция для класса cls3

 

 

};

cls3(int cc): c(cc) {}

// конструктор класса cls3

 

 

 

 

 

 

 

 

 

 

 

 

cls1(int aa): a(aa) {}

// конструктор класса cls

 

 

};

 

 

 

 

 

 

 

 

 

 

 

void main()

 

 

 

 

 

 

 

 

{ cls1 aa(1980);

 

// верно

 

 

cls1::cls2 bb(456);

// ошибка cls2 cannot access private

 

cls1::cls3 cc(789);

// верно

 

 

 

 

 

 

 

 

 

 

 

 

45

cout << aa.a << endl;

// верно

 

cout << cc.c << endl;

// ошибка

'c' : cannot access private member

 

//

declared in class 'cls1::cls3'

}

В приведенном тексте программы инструкция cls1::cls2 bb(456) является ошибочной, так как объявление класса cls2 и его компонента находятся в сек- ции private. Для устранения ошибки при описании объекта bb необходимо из-

менить атрибуты доступа для класса cls2 следующим образом:

 

public:

 

 

 

 

 

 

 

 

Р

 

class cls2

 

 

 

 

 

 

 

 

 

{

int b;

 

// private-компонента

 

 

 

public:

 

 

 

 

 

 

 

 

 

};

cls2(int bb) : b(bb){}

 

 

 

У

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Г

 

Пример доступа

к private-компонентам вложенного классаИиз функций

внешнего класса, объявленных со спецификатором friend, приводится ниже.

#include <iostream>

 

 

 

 

Б

 

 

 

 

 

 

 

 

 

using namespace std;

 

 

 

// внешний класс

 

 

class cls1

 

 

 

 

 

 

 

{

int a;

 

 

 

 

 

 

а

 

 

 

public:

 

 

 

 

 

е

 

 

 

cls1(int aa): a(aa) {}

 

 

 

 

class cls2;

 

 

 

 

// нкполное объявление класса

 

 

void fun(cls1::cls2);

т

 

 

 

 

 

// функция получает объект класса cls2

 

class cls2

 

о

// вложенный класс

 

 

 

{

int c;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

public:

 

 

 

 

 

 

 

 

 

 

 

cls2(int cc) : c(cc) {}

 

 

 

 

 

 

 

 

л

 

 

 

 

 

 

 

 

 

friend void cls1::fun(cls1::cls2); // функция, дружественная

 

 

 

int pp(){returnиc;}

 

// классу cls1

 

 

 

};

 

 

 

 

 

 

 

 

 

};

и

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Б

 

 

 

 

 

 

 

 

 

void cls1::fun(cls1::cls2б

dd) {cout << dd.c << endl << a;}

 

 

int main()

 

 

 

 

 

 

 

 

 

{

cls1 aa(123);

 

 

 

 

 

 

 

 

 

cls1:: cls2 cc(789);

 

 

 

 

 

 

 

 

aa.fun(cc);

 

 

 

 

 

 

 

 

 

return 0;

}

Внешний класс cls1 содержит public-функцию fun(cls1::cls2 dd), где dd

есть объект, соответствующий классу cls2,

вложенному в класс cls1. В свою

очередь в классе cls2 имеется friend-функция

friend void cls1::fun(cls1::cls2 dd),

46

 

обеспечивающая доступ функции fun класса cls1 к локальной компоненте с класса cls2.

#include <iostream> using namespace std; #include <string.h>

 

class ext_cls

 

 

 

 

//

внешний класс

 

 

{ int gd;

 

 

 

 

// год рождения

 

 

double zp;

 

 

 

// з/плата

 

 

 

 

 

class int_cls1

 

 

//

первый вложенный класс

 

 

 

{

 

char *s;

 

 

 

// фамилия

 

 

 

 

 

public:

 

 

 

 

// конструктор 1-го вложенногоИРкласса

 

 

 

 

int_cls1(char *ss)

 

 

 

 

{ s=new char[20];

 

 

 

 

 

 

 

 

 

 

}

strcpy(s,ss);

 

 

 

 

 

Г

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Б

 

 

 

 

~int_cls1()

 

 

// деструктор 1-го вложенногоУ

класса

 

 

 

{ delete [] s;}

 

 

 

 

 

 

 

 

 

 

void disp_int1() {cout << s<<endl;}

 

 

 

 

};

 

 

 

 

 

 

 

 

 

а

 

 

 

public:

 

 

 

 

 

к

 

 

 

 

class int_cls2

 

е

 

 

 

 

 

 

 

//

второй вложенный класс

 

 

{

}

char *s;

 

т

// фамилия

 

 

 

 

 

public:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

int_cls2(char *ss)

 

//конструктор 2-го вложенного класса

 

 

 

 

 

 

о

 

 

 

 

 

 

 

 

 

 

{ s=new char[20];

 

 

 

 

 

 

 

 

 

 

 

strcpy(s,ss);

 

 

 

 

 

 

 

 

 

 

 

 

и

 

 

// деструктор 2-го вложенного класса

 

 

л

 

 

 

 

 

 

 

~int cls2()

 

 

 

 

 

 

{ delete [] s;}

 

 

 

 

 

 

 

 

б

 

 

int2() {cout << s << endl;}

 

 

 

 

};

void disp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Б

 

 

 

// public функции класса ext_cls

 

 

 

и

ext_cls(int god,double zpl):gd(god),zp(zpl){}// конструктор внешнего

 

 

 

 

 

 

 

 

 

 

 

 

// класса

 

 

 

int_cls1 *addr(int_cls1 &obj){return &obj;} // возврат адреса объекта obj

 

 

void disp_ext()

 

 

 

 

 

 

 

 

 

 

{

int_cls1 ob("Иванов");

// создание объекта вложенного класса

 

 

 

addr(ob)->disp_int1();

 

// вывод на экран содержимого объекта ob

 

 

}

cout <<gd<<’ ’<< zp<<endl;

 

 

 

 

};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

47

int main()

{ext_cls ext(1980,230.5);

//ext_cls::int_cls1 in1("Петров"); // неверно, т.к. int_cls1 имеет

//атрибут private

ext_cls::int_cls2 in2("Сидоров");

 

 

in2.disp_int2();

 

 

ext.disp_ext();

//

 

return 0;

 

 

}

 

 

Р

В результате выполнения программы получим:

Сидоров

 

Иванов

 

1980

230.5

 

 

 

В строке in2.disp_int2() (main функции) для объекта вложенного класса

 

 

 

И

вызывается компонента-функция ext_cls::int_cls2::disp_int2() для вывода содер-

жимого объекта in2 на экран. В следующей строке ext.dispГУext() вызывается функция ext_cls::disp_ext(), в которой создается объект вложенного класса int_cls1. Затем, используя косвенную адресацию, вызывается функция

ext_cls::int_cls1::disp_int1(). Далее выводятся д нные, содержащиеся в объекте

внешнего класса.

Б

а

3.9. Static-члены (данные) класса

Компоненты-данные могут быть объявлкны с модификатором класса па-

мяти static. Класс, содержащий static компон нты-данные, объявляется как гло-

е

 

бальный (локальные классы не могут иметь статических членов). Static-

компонента совместно исп льзуе ся всеми объектами этого класса и хранится в

одном месте. Статическая к мп нен глобального класса должна быть явно

 

 

 

 

та

 

 

 

о

 

 

и

 

определена в контексте файла. Использование статических компонент-данных

класса продемонстрируем на примере программы, выполняющей поиск введен-

ного символа в строке.

 

 

 

#include "string.h"

 

 

 

л

 

 

#include "iostream.h"

 

 

enum boolean {fls,tru};

 

class cls

б

 

 

 

{ charи*s;

 

 

 

public:

 

 

 

Б

 

 

// объявление static-члена в объявлении класса

static int k;

 

static boolean ind;

 

void inpt(char *,char);

 

void print(char);

 

 

};

 

 

 

 

int cls::k=0;

 

// явное определение static-члена в контексте файла

48

 

boolean cls::ind;

 

 

 

 

 

 

 

 

void cls::inpt(char *ss,char c)

 

 

 

 

 

{ int kl;

 

// длина строки

 

 

 

 

 

cin >> kl;

 

 

 

 

 

 

 

 

 

ss=new char[kl];

 

// выделение блока памяти под строку

 

cout << "введите строку\n";

 

 

 

 

 

 

cin >> ss;

 

 

 

 

 

 

 

 

 

for (int i=0; *(ss+i);i++)

 

 

 

 

 

Р

 

if(*(ss+i)==c) k++;

// подсчет числа встреч буквы в строке

 

if (k) ind=tru;

 

// ind==tru − признак того, что буква есть в строке

 

delete [] ss;

 

 

 

 

 

 

И

}

 

 

 

 

 

 

У

 

void cls::print(char c)

 

 

 

 

 

 

 

 

 

 

 

 

{ cout << "\n число встреч символа "<< c <<"в строках = " << k;

}

 

 

 

 

 

Г

 

 

void main()

 

 

 

 

 

 

{ cls c1,c2;

 

 

 

 

 

 

 

char c;

 

 

 

а

 

 

 

 

char *s;

 

 

к

Б

 

 

 

 

cls::ind=fls;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

cout << "введите символ для поис в строках";

 

 

 

cin >> c;

т

 

 

 

 

 

 

 

c1.inpt(s,c);

 

е

 

 

 

 

 

 

c2.inpt(s,c);

 

 

 

 

 

 

 

if(cls::ind) c1.print(c);

 

 

 

 

 

 

 

else cout << "\n символ не найден";

 

 

 

 

}

и

 

 

 

 

 

 

 

 

 

л

 

 

 

 

 

 

 

 

Объяв ен еостатических компонент-данных задает их имена и тип, но не

инициа изирует значениями. Присваивание им некоторых значений выполняет-

 

б

 

ся в программе (вне объекта).

 

В функции main() использована возможная форма обращения к static-

компоненте

 

 

cls::ind

(имя класса :: идентификатор),

котораяиобеспечивается тем, что идентификатор имеет видимость public. Это

дальнейшее использование оператора разрешения контекста “::”.

Б

Отметим основные правила использования статических компонент:

-статические компоненты будут одними для всех объектов данного клас- са, т.е. ими используется одна область памяти;

-статические компоненты не являются частью объектов класса;

-объявление статических компонент-данных в классе не является их опи- санием. Они должны быть явно описаны в контексте файла;

-локальный класс не может иметь статических компонент;

49

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