C++ 3d.Комментарии




Указатели на члены


Поэтому указатель на виртуальный член можно безопасно передавать из одного адресного пространства в другое...

Это утверждение, вообще говоря, неверно и я вам советую никогда так не поступать. Сейчас покажу почему.

Прежде всего, стоит отметить, что в C++ вы не сможете прямо вывести значение указателя на член: struct S { int i; void f(); };

void g() { cout<<&S::i; // ошибка: operator<< не реализован для типа int S::* cout<<&S::f; // ошибка: operator<< не реализован для типа void (S::*)() }

Это довольно странно. Andrew Koenig пишет по этому поводу, что дело не в недосмотре разработчиков библиотеки ввода/вывода, а в том, что не существует переносимого способа для вывода чего-либо содержательного (кстати, я оказался первым, кто вообще об этом спросил, так что проблему определенно нельзя назвать злободневной). Мое же мнение состоит в том, что каждая из реализаций вполне способна найти способ для вывода более-менее содержательной информации, т.к. в данном случае даже неидеальное решение -- это гораздо лучше, чем вообще ничего.

Поэтому для иллюстрации внутреннего представления указателей на члены я написал следующий пример: #include <string.h> #include <stdio.h>

struct S { int i1; int i2;

void f1(); void f2();

virtual void vf1(); virtual void vf2(); };

const int SZ=sizeof(&S::f1);

union { unsigned char c[SZ]; int i[SZ/sizeof(int)]; int S::* iptr; void (S::*fptr)(); } hack;

void printVal(int s) { if (s%sizeof(int)) for (int i=0; i<s; i++) printf(" %02x", hack.c[i]); else for (int i=0; i<s/sizeof(int); i++) printf(" %0*x", sizeof(int)*2, hack.i[i]);

printf("\n"); memset(&hack, 0, sizeof(hack)); }

int main() { printf("sizeof(int)=%d sizeof(void*)=%d\n", sizeof(int), sizeof(void*));

hack.iptr=&S::i1; printf("sizeof(&S::i1 )=%2d value=", sizeof(&S::i1)); printVal(sizeof(&S::i1));

hack.iptr=&S::i2; printf("sizeof(&S::i2 )=%2d value=", sizeof(&S::i2)); printVal(sizeof(&S::i2));




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