@robcio
Przeciez jak mamy wskaznik na inta ,na chara, czy na funkcje to jego rozmiary sa takie same w danej architekturze
Właśnie z tymi wskaźnikami na funkcje nie jest do końca tak jak mówisz, a w zasadzie z ich pewnym rodzajem - wskaźnikami na funkcje składowe (czy też metody). Te wskaźniki mogą mieć inne rozmiary niż pozostałe rodzaje wskaźników. Przykład:
#include <iostream>
using namespace std;
class Base {
public:
Base(){}
virtual void foo(int){ cout << "Base::foo(int);\r\n"; }
virtual ~Base() {}
};
class Inherited : public Base {
public:
Inherited() : Base() {}
void foo(int) { cout << "Inherited::foo(int);\r\n"; }
void foo2() { cout << "Inherited::foo2();\r\n"; }
};
void foo(int, int) { cout << "foo(int, int);\r\n"; }
typedef void (*PFoo)(int, int);
typedef void (Base::*PBaseFoo)(int);
typedef void (Inherited::*PInheritedFoo)(int);
typedef void (Inherited::*PInheritedFoo2)();
int main()
{
PFoo pf = &foo;
PBaseFoo pbf = &Base::foo;
PInheritedFoo pif = &Base::foo;
PInheritedFoo pif2 = &Inherited::foo;
PInheritedFoo2 pif3 = &Inherited::foo2;
Base *b1 = new Base();
Base *b2 = new Inherited();
Base b3;
Inherited *i1 = new Inherited();
Inherited i2;
//przy okazji przykład użycia
cout << "(*pf) : "; (*pf)(0, 0);
cout << "(b1->*pbf) : "; (b1->*pbf)(1);
cout << "(b2->*pbf) : "; (b2->*pbf)(2);
cout << "(b3.*pbf) : "; (b3.*pbf)(3);
cout << "(i1->*pbf) : "; (i1->*pbf)(4);
cout << "(i1->*pif) : "; (i1->*pif)(5);
cout << "(i1->*pif2) : "; (i1->*pif2)(6);
cout << "(i1->*pif3) : "; (i1->*pif3)();
cout << "(i2.*pbf) : "; (i2.*pbf)(7);
cout << "(i2.*pif) : "; (i2.*pif)(8);
cout << "(i2.*pif2) : "; (i2.*pif2)(9);
cout << "(i2.*pif3) : "; (i2.*pif3)();
//rozmiary
cout << "\r\nsizeof(int*) = " << sizeof(int*)
<< "\r\nsizeof(PFoo) = " << sizeof(PFoo)
<< "\r\nsizeof(PBaseFoo) = " << sizeof(PBaseFoo)
<< "\r\nsizeof(PInheritedFoo) = " << sizeof(PInheritedFoo)
<< "\r\nsizeof(PInheritedFoo2) = " << sizeof(PInheritedFoo2);
delete i1;
delete b2;
delete b1;
return 0;
}
w moim przypadku (windows xp 32 bit + mingw32(z gcc 4.4.1)) powyższy kod daje następujące wyjście:
(*pf) : foo(int, int);
(b1->*pbf) : Base::foo(int);
(b2->*pbf) : Inherited::foo(int);
(b3.*pbf) : Base::foo(int);
(i1->*pbf) : Inherited::foo(int);
(i1->*pif) : Inherited::foo(int);
(i1->*pif2) : Inherited::foo(int);
(i1->*pif3) : Inherited::foo2();
(i2.*pbf) : Inherited::foo(int);
(i2.*pif) : Inherited::foo(int);
(i2.*pif2) : Inherited::foo(int);
(i2.*pif3) : Inherited::foo2();
sizeof(int*) = 4
sizeof(PFoo) = 4
sizeof(PBaseFoo) = 8
sizeof(PInheritedFoo) = 8
sizeof(PInheritedFoo2) = 8
Poza tym wskaźniki na funkcje mogą mieć różne rozmiary w zależności od wykorzystywanej architektury - czy to architektury harwardzkiej czy von Neumana bądź mieszanej. Są to specyficzne zastosowania jednak nie można stwierdzić, że ten rodzaj wskaźników posiada zawsze taki sam rozmiar jak pozostałe rodzaje, a tym bardziej nie polecałbym na tym bazować bo kiedyś można się przejechać.
Sądzę, że jest to również jeden z powodów dla których standard nie gwarantuje iż void* przechowa wskaźnik na dowolną funkcję przez co należy taką operację uznać za zachowanie niezdefiniowane.