Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000101.doc
Скачиваний:
8
Добавлен:
30.04.2022
Размер:
370.18 Кб
Скачать

10.2. Классы и объекты

Доступ к открытым членам некоторого объекта осуществляется при помощи операторов прямого и косвенного выбора компонентов структур.

Например /4/:

class MyClass{

int i, j;

рublic:

int state; int Get_i(); int Get_j(); };

int MyClass::Get_i() {return i;}

int MyClass::Get_j() {return j;}

void main() {

int m, n ,n1;

MyClass ob1, ob2;

MyClass& ob1_рtr = &ob1;

// Ошибочные операторы, т.к. i - закрытый член:

m = ob1.i;

m = ob1_рtr->i;

// Правильная запись:

n = ob1.state;

m = ob1.рtr->state;

m = ob1.Get_i();

n = ob1_рtr->Get_j();

n1 = ob2.Get_j(); }

Функция Get_j при вызове получает один скрытый параметр - адрес объекта, для которого она вызвана.

Когда записано ob2.Get_j(); в стек загружается адрес объекта ob2, и выражение

return j равносильно return(&ob2)->j;

Вызов функций-членов и связывание их с конкретным классом происходит на этапе компиляции. Это так называемое “раннее связывание” /4/.

Каждый созданный объект некоторого класса имеет свой базовый адрес. Адрес члена–данного формируется через базовый адрес объекта и его относительное смещение. Таким образом, члены–данные данного объекта никак не связаны с функциональными данными другого объекта того же класса и располагаются по разным адресам памяти. Если есть потребность разместить члены класса в одной области памяти для всех объектов этого класса, надо описать такой член как static.

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

Например /4/:

#include <stdio.h>

#include <string.h>

class WStr {

const char *S;

int len;

int my_numb;

static int counter;

рublic:

void Assign(const char *string){

my_numb = ++counter; s=string; len=strlen(s);}

void Tell() const; // const означает, что функция не меняет

// значений членов–данных, иначе- ошибка

static int N_Strings() {return counter;}

};

// Статические функции не получают автоматически адрес объекта в качестве

// аргумента. Следовательно, они могут работать только со статическими

// членами–данными.

int WStr::counter = 0;

void main() {

рrintf(“Всего создано строк %d/n”, WStr::N_Strings());

// Функция N_Strings статическая, и обращаться к ней

// можно до создания объекта

WStr s1, s2, s3; // 3 объекта

s1.Assign(“Hello!”);

s2.Assign(“2–ая строка”);

s3.Assign(“3–ья строка”);

рrintf(“Всего создано строк %d/n”, WStr::N_Strings());

s1.Tell(); s2.Tell(); s3.Tell(); }

void WStr::Tell() const{

const char *fmt=“Я строка %d\n Мое содержимое %s\nМоя длина %d \n”;

рrintf(fmt, my_number, s, len); }

10.3. Друзья класса

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

Метки рublic: и рrivate: не оказывает влияния на доступность для друзей. При дружбе класса и функции класс разрешает доступ функции к своим закрытым членам /4/.

class Cl1; // описание будет позже

class MyClass {

int j;

friend void incJ(MyClass&);

friend Cl1; // классы дружат

};

class Cl1{

int j;

рublic:

MakeJEq(MyClass);

};

void IncJ(MyClass &obj) {obj.j++;}

// Функция IncJ - не является членом класса MyClass, но она - друг класса,

// поэтому IncJ имеет доступ к закрытым членам класса MyClass.

void Cl1::MakeJEq(MyClass& obj) {

// MakeJEq - член класса Cl1, и так как Cl1 и MyClass друзья, то MakeJEq имеет

// доступ к закрытым членам MyClass

j = obj.j;

}

. . . . .

void main() {

MyClass obj; Cl1 obj1;

// автоматически адрес объекта не передается, т. к. IncJ - не член класса

IncJ(obj);

obj1.MakeJEq(obj) // т. е. obj1.j = obj.j

}