Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Указатели на компоненты класса. Доступ по указателю

Прежде всего, рассмотрим объявление класса XXX.

class XXX
{
public:
 long x1;
 int x2;
/*Данные-члены класса.*/
 long getVal1() {return x1;}
 long getVal2() {return x2*x1;}
/*Функции-члены класса без параметров.*/
 int   getVal3(int param)  {return x2*param;}
 char* getVal4(char *str) {return str;}
/*Функции-члены класса с параметрами.*/
 static int f1() {return 100;}
 static int f2() {return 10;}
 static int f3(int param) {return param;}
/* Определение различных статических функций*/
 XXX(long val1, int val2){x1 = val1; x2 = val2;}
/*Конструктор.*/
};

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

Для объявления указателя на нестатическую функцию используется специальная синтаксическая конструкция, состоящая из спецификатора объявления и заключённого в скобки квалифицированного имени указателя, состоящего из имени класса, операции доступа к члену класса ::, разделителя * , собственно имени указателя, закрывающей скобки и списка параметров:

int (XXX::*fp_3) (int);

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

int (XXX::*fp_3) (int) = &XXX::getVal1;

Вот и нашлась достойная область применения квалифицированным именам.

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

Fp_3 = XXX::getVal2

Класс - это не объект! И не совсем понятно, какое значение имеет адрес нестатичесного члена класса. Значение проинициализированного указателя на нестатическую компоненту остаётся неопределённым.

Оно определяется лишь в результате выполнения операций обращения к членам класса .* и ->* .

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

int val = (q.*fp)(6);
char val = (pq->*fp4)("new string");

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

long (XXX::*px1) = &XXX::x1;
// Определение и инициализация указателя на член класса XXX типа long
q.*px11 = 10; // p - объект-представитель класса XXX.
pq->*px11 = 10;
// pq - указатель на объект-представитель класса XXX.

Основные приёмы работы с указателями на функции-члены демонстрируются на следующих примерах:

class XXX
{
public:
 long x1;
 int x2;
/*Данные-члены класса.*/
 long getVal1() {return x1;}
 long getVal2() {return x2*x1;}
/*Функции-члены класса без параметров.*/
 int   getVal3(int param)  {return x2*param;}
 char* getVal4(char *str) {return str;}
/*Функции-члены класса с параметрами.*/
 static int f1() {return 100;}
 static int f2() {return 10;}
 static int f3(int param) {return param;}
/* Определение различных статических функций*/
 XXX(long val1, int val2){x1 = val1; x2 = val2;}
/*Конструктор.*/
};
void main()
{
 XXX  q(1,2);/* Определение объекта.*/
 XXX* pq = new (XXX);
 pq->x1 = 100;
 pq->x2 = 100;
/*Определение и инициализация объекта по указателю.*/
 long (XXX::*fp_0) ();
/*Указатель на функцию-член класса.*/
 long (XXX::*fp_1) () = &XXX::getVal1;
/*
Проинициализированный указатель на функцию-член класса. Его
значение является относительной величиной и равняется значению
смещения функции-члена относительно первого члена класса.
*/
 fp_0 = XXX::getVal1;
/*
Инициализация первого указателя. Один и тот же указатель можно
настраивать на различные функции-члены класса. Главное, чтобы у
всех этих функций-членов совпадали списки параметров и возвращаемые
значения функций.
*/
 long val_1 = (q.*fp1)(); 
/*Вызов функции-члена класса по указателю из объекта.*/
 
 long val_2 = (pq->*fp0)();
/*
Вызов функции-члена класса по указателю с помощью указателя на объект.
*/
 int (XXX::*fp_3) (int) = &XXX::getVal3;
/*
Проинициализированный указатель на функцию-член класса. С параметрами
типа int.
*/
 int val_3 = (q.*fp_3)(6);
/*
Вызов функции-члена класса по указателю из объекта с передачей параметров.
*/
char* (XXX::*fp_4) (char) = &XXX::getVal3;
/*
Проинициализированный указатель на функцию-член класса с параметрами типа int.
*/
char val_4 = (pq->*fp4)("new string");
/*
Вызов функции-члена класса по указателю с помощью указателя на объект.
*/
int (*fp_5) () = &XXX::f1;
/*
Указатель на статическую функцию объявляется без спецификации класса.
Явная спецификация класса необходима лишь при инициализации указателя.
*/
int retval = (*fp_5)();
/*Вызов статической функции по указателю.*/
fp_5 = XXX::f2;
/*
Перенастройка статического указателя. Главное требование - совпадение
списков параметров и типа возвращаемого значения.
*/
int (*fp_6) (int) = &XXX::f3;
/*Указатель на статическую функцию с параметрами.*/
int retval = (*fp_6)(255);
/*Вызов статической функции с параметрами по указателю.*/
long (XXX::*px1) = &XXX::x1;
/*Определили и проинициализировали указатель на член класса long*/
q.*px11 = 10;
/*Используя указатель на компоненту класса, изменили значение переменной
x1 объекта q, представляющего класс XXX. */
pq->*px11 = 10;
/*Используя указатель на компоненту класса, изменили значение переменной
x1 объекта, представляющего класс XXX и расположенного по адресу pq. */
}

Вызов статических функций-членов класса не требует никаких объектов и указателей на объекты. От обычных функций их отличает лишь специфическая область видимости.

Назад | Содержание | Вперед

 

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в 21 локации

От 104 рублей в месяц

Безлимитный трафик. Защита от ДДоС.

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...