Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Указатели на компоненты-данные




Можно определить указатель на компоненты-данные.

тип_данных(имя_класса::*имя_указателя)

В определении указателя можно включить его инициализатор

&имя_класса:: имя_компонента

Пример. double(complex::*pdat) = &complex:: re;

Естественно, что в этом случае данные-члены должны иметь статус открытых(pubic).

После инициализации указателя его можно использовать для доступа к данным объекта.

complex c(10.2,3.6);

c/*pdat=22.2; //изменилось значение поля re объекта c.

Указатель на компонент класса можно использовать в качестве фактического параметра при вызове функции.

Если определены указатели на объект и на компонент, то доступ к компоненту с помощью операции ‘ –>* ’.

указатель_на_объект –>*указатель_на_компонент

Пример 1.5.1.

double(complex::*pdat) = &complex:: re;

complex C(10.2,3.6);

complex *pcom = &C;

pcom –>*pdat = 22.2;

 

Можно определить тип указателя на компоненты-данные класса:

typedef double(complex::*PDAT);

void f(complex c, PDAT pdat) {c.*pdat=0;}

complex c;

PDAT pdat=&complex::re; f(c,pdat);

pdat=&complex::im; f(c,pdat);

 

Указатели на компоненты-функции

Можно определить указатель на компоненты-функции.

тип_возвр_значения(имя_класса::

*имя_указателя_на_функцию)(специф_параметров_функции);

Пример 1.5.1.

// Определение указателя на функцию–член класса

double(complex::*ptcom)();

// Настройка указателя

ptcom = &complex:: real;

// Теперь для объекта А

complex A(5.2,2.7);

// можно вызвать его функцию

cout<<(A.*ptcom)();

// Если метод real определить типа ссылки

double& real(void){return re;}

// то используя этот метод можно изменить поле re

(A.*ptcom)() = 7.9;

// При этом указатель определяется так

double&(complex::*ptcom)();

 

Можно определить также тип указателя на функцию

typedef double&(complex::*PF)();

а затем определить и сам указатель

PF ptcom=&complex::real;

Указатель this

Когда функция-член класса вызывается для обработки данных конкретного объекта, этой функции автоматически и неявно передается указатель на тот объект, для которого функция вызвана. Этот указатель имеет имя this и неявно определен в каждой функции класса следующим образом:

имя_класса *const this = адрес_объекта

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

В большинстве случаев использование this является неявным. В частности, каждое обращение к нестатической функции–члену класса неявно использует this для доступа к члену соответствующего объекта. Например, функцию add в классе complex можно определить эквивалентным, хотя и более пространным способом:

void complex add(complex ob)

{this->re=this->re+ob.re;

// или *this.re=*this.re+ob.re

this->im=this->im+ob.im;}

Если функция возвращает объект, который ее вызвал, используется указатель this.

Например, пусть функция add возвращает ссылку на объект. Тогда

complex& complex add(complex& ob)

{re=re+ob.re;

im=im+ob.im;

return *this;

}

Примером широко распространенного использования this являются операции со связанными списками.

Пример. 1.6.1.Связанный список.

#include <iostream.h>

//Определение класса

class item

{

static item *begin;

item *next;

char symbol;

public:

item (char ch){symbol = ch;} // конструктор

void add(void); // добавить в начало

static void print(void);

};

//Реализация класса

void item:: add(void)

{

this –>next = begin;

begin = this;

}

void item:: print(void)

{

item *p;

p = begin;

while(p!= NULL)

{

cout<<p –>symbol<<“ \t ”;

p = p –>next;

}

}

//Создание и просмотр списка

item *item:: begin = NULL; // инициализация статического компонента

void main ()

{

item A(‘a’); item B(‘b’); item C(‘c’);

// включение объектов в список

A.add(); B.add(); C.add();

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

item:: print();

}

 

Друзья классов

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

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

Пример 1.7.1

class myclass

{

int x,y;

friend void set(myclass*,int,int);

public:

myclass(int x1,int y1){x = x1; y = y1;}

int sum(void){return (x+y);}

};

void set(myclass *p,int x1,int y1){p–>x = x1; p–>y = y1;}

void main (void)

{

myclass A(5,6);

myclass B(7,8);

cout<<A.sum();

cout<<B.sum();

set(&A,9,10);

set(&B,11,12);

cout<<A.sum();

cout<<B.sum();

}

Функция set описана в классе myclass как дружественная и определена как обычная глобальная функция (вне класса, без указания его имени, без операции ‘:: ‘ и без спецификатора friend).

Дружественная функция при вызове не получает указатель this. Объекты класса должны передаваться дружественной функции только через параметр.

Итак, дружественная функция:

· не может быть компонентной функцией того класса, по отношению к которому определяется как дружественная;

· может быть глобальной функцией;

· может быть компонентной функцией другого ранее определенного класса.

Например,

class CLASS1

{...

int f(...);

...

};

class CLASS2

{...

friend int CLASS1:: f(...);

...

};

// В этом примере класс CLASS1 с помощью своей компонентной функции f()

// получает доступ к компонентам класса CLASS2.

· может быть дружественной по отношению к нескольким классам;

Например,

// предварительное неполное определение класса

class CL2;

class CL1

{friend void f(CL1,CL2);

...

};

class CL2

{friend void f(CL1,CL2);

...

};

// В этом примере функция f имеет доступ к компонентам классов CL1 и CL2.

 

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

Класс может быть дружественным другому классу. Это означает, что все компонентные функции класса являются дружественными для другого класса. Дружественный класс должен быть определен вне тела класса «предоставляющего дружбу».

Например,

class X2{friend class X1;...};

class X1

{...

void f1(...);

void f2(...);

...

};

// В этом примере функции f1 и f2 класса Х1 являются друзьями класса Х2, хотя они

// описываются без спецификатора friend.

Пример 1.7.2.

Рассмотрим класс point – точка в n-мерном пространстве и дружественный ему класс vector – радиус-вектор точки («вектор с началом в начале координат n-мерного пространства»). В классе vector определим функцию для определения нормы вектора, который вычисляется как сумма квадратов координат его конца.

class point

{int N; // размерность

double *x; // указатель на массив координат

friend class vector;

public:

point(int n,double d = 0.0);

};

point:: point(int n,double d)

{N = n;

x = new double[N];

for(int i = 0; i < N; i++) x[i] = d;

}

class vector

{double *xv;

int N;

public:

vector(point,point);

double norma();

};

vector:: vector(point begin,point end)

{N = begin.N;

xv = new double[N];

for(int i = 0; i < N; i++) xv[i] = end.x[i]–begin.x[i];

}

double vector:: norma()

{double dd = 0.0;

for(int i = 0; i < N; i++) dd += xv[i]*xv[i];

return dd;

}

void main (void)

{point A(2,4.0);

point B(2,2.0);

vector V(A,B);

cout<<V.norma();

}

// Будет выведено – 8.

Недостатком предложенного класса point является то, что значения всех координат точки x[i] одинаковы. Чтобы они были произвольными и разными, необходимо определить конструктор как функцию с переменным числом параметров, например так:

point:: point(int n,double d,...)

{

N = n;

x = new double[N];

double *p = &d;

for(int i = 0; i < N; i++){x[i] = *p; p++;}

}

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...