Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
63
Добавлен:
16.02.2016
Размер:
455 Кб
Скачать

Использование указателей на функции-члены класса

Можно определить указатель на функцию-член класса. Син­таксис определения следующий:

<возвр_тип>

(<имя_класса>: : *<имя_указателя>) (<параметры>) ;

Например:

void (Т::*funcPtr)(int х, int у);

Таким образом, синтаксис определения указателя на функ­цию-член класса отличается от объявления указателя на обычную функцию тем, что в круглых скобках указывается имя класса, отделенное от имени указателя символом расширения области видимости, а само имя указателя предваряется звездочкой. Эта звездочка должна напомнить программисту, что при использова­нии такой указатель должен разыменовываться (в отличие от ука­зателя на обычную функцию). Например,

this->*funcPtr(x,y);

или

*this.* funcPtr(x,y);

Указателю на функцию-член класса передается скрытый ука­затель this (иначе ему нельзя было бы присвоить значение ад­реса некоторой функции-члена класса).

Следующий пример демонстрирует использование указателей на функцию-член.

class Т

{

int i;

public:

Т (int _I) : i (_i) { }

void MembFunc() {printf ("Hello! ") ; }

void CallMembFunc(void (T::*funcPtr)() }

{

this->*funcPtr)();

}

};

int main()

{

void (T::*funcPtr)() = &T::MembFunc;

Т ob(2000);

ob.CallMembFunc(funcPtr) ;

return 0;

}

C++ накладывает определенные ограничения на использова­ние указателей на функции-члены класса:

• указатель на функцию-член класса не может ссылаться на статическую функцию-член класса (так как ей не пе­редается указатель this);

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

Массивы объектов класса

Из объектов класса, как и из обычных переменных, можно строить массивы. Синтаксис объявления массива объектов анало­гичен синтаксису объявления массивов обычных переменных. Например, следующее объявление создает массив из 10 элемен­тов, которые являются объектами класса AnyClass:

AnyClass obArr[10];

Однако для того, чтобы компилятор смог создать этот массив, он должен использовать конструктор по умолчанию объектов класса. В отношении конструктора по умолчанию действуют пе­речисленные нами ранее правила. Рекомендуем не полагаться на то, что компилятор сам создаст конструктор по умолчанию, и всегда при объявлении массива объектов некоторого класса включать в этот класс конструктор по умолчанию.

Доступ к элементам массива также аналогичен доступу к мас­сивам переменных любого другого типа. Например,

#include <iostream.h>

class AnyClass

{

int a;

public:

AnyClass(int n) {a = n;}

int GetA()(return a;}

};

main ()

{

//Объявление и инициализация массива объектов

AnyClass obArr[5] = {13, 17, 21, 23, 27};

int i;

for (i=0; i<4; i++)

{

//Обращение к элементам массива

cout « obArr[i].GetA() « ' ' ;

}

cout « "\n";

return 0;

}

Эта программа выводит на экран проинициализированные значения массива объектов obАrr. Фактически, примененный здесь синтаксис инициализации массива является сокращенной формой следующей конструкции:

AnyClass obArr[5] = {AnyClass(13),

AnyClass(17),

AnyClass(21) ,

AnyClass(23),

AnyClass(27)};

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

#include <iostream.h>

class Coord

{

int x, у;

public:

Coord(int _x, int _y) {x = _x; у = _y;}

int GetX(){return x;}

int GetY(){return y;}

};

main()

{

Coord coordArr[4][2] = {Coord(3,4), Coord(5,6), Coord(7,8), Coord(9,10), Coord(11,12), Coord(13,14), Coord(15,16), Coord(17,18),

};

int i, j;

for (i=0; i<4; i++)

for (j=0; j<2; j++)

{

cout « coordArr[i][j].GetX() « ' ' ;

cout « coordArr[i][j].GetY() « ' ' ;

}

cout « "\n";

return 0;

}

Использование указателей для доступа к объектам массива совершенно аналогично их использованию для обычных пере­менных и структур. Арифметика указателей также аналогична. Инкрементирование указателя приводит к тому, что он указы­вает на следующий объект массива, декрементирование — к тому, что он указывает на предыдущий объект массива. Рас­смотрим пример:

#include <iostream.h>

class Coord

{

int x, у;

public:

Coord(int _x, int _y) {x = _x; у = _y;}

int GetX(){return x;}

int GetY(){return y;}

};

main()

{

Coord obArr[4] = {

Coord(3,4), Coord(5,6), Coord(7,8), Coord(9,10), Coord(11,12), Coord(13,14), Coord(15,16), Coord(17,18)

};

int i;

Coord* ptr;

ptr = obArr; //Инициализация указателя адресом массива

for (i=0; i<4; i++)

{

cout « ptr->GetX() « ' ';

cout « ptr->GetY() « "\n";

ptr++; //Переход на следующий объект

}

cout « "\n";

return 0;

}

Эта программа выводит на экран в каждой строке значения переменных х и у текущего элемента массива объектов.

Массивы объектов классов могут располагаться в куче. На­пример:

#include <iostream.h>

class Coord

{

int х, у;

public:

Coord(int _x, int _y){x = _х; у = _у;}

Coord(){x = 0; у = 0;}

int GetX(){return x;}

int GetY(){return y;}

};

main()

{

int i;

Coord* ptr;

//Создание массива объектов в куче

ptr = new Coord[6];

for (i=0; i<6; i++)

{

cout « ptr->GetX() « ' ';

cout « ptr->GetY() « "\n";

ptr++; //Переход на. следующий объект

}

cout « "\n";

//Удаление массива объектов из кучи

delete[] ptr;

return 0;

}

Следует обратить внимание, что для удаления массива объектов используется форма оператора delete с квадратными скобками.

Соседние файлы в папке ЯзыкС++Глушаков