Odnośnie konkretnej kwestii,
jak możemy obserwować treść wskaźników funkcji członkiem?
Odpowiedź brzmi, inne niż konwersja ich na wartość bool, aby wyrazić, że wskazuje na coś lub nie, nie można "obserwować" wskaźników funkcji członków. Przynajmniej nie w zgodny sposób. Powodem tego jest fakt, że standardowy wyraźnie uniemożliwia to:
4,12 Przypis 57:
57) Zasada do konwersji odnośniki do członkowie (wskaźnik do członka podstawy do wskaźnika członkowi pochodzącego) jest odwrócony w porównaniu z regułą dla wskaźników do obiektów (od wskaźnik do wyprowadzenia na wskaźnik do bazy) (4.10, punkt 10). Ta inwersja to niezbędna do zapewnienia bezpieczeństwa typu. Uwaga: , że wskaźnik do elementu nie jest wskaźnikiem obiektu lub wskaźnikiem do funkcji , a zasady dotyczące konwersji takich wskaźników nie mają zastosowania do wskaźników dla członków.W szczególności, wskaźnik dla członka nie może zostać przekształcony w pustkę *.
Na przykład, oto przykładowy kod:
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
class Gizmo
{
public:
void DoTheThing()
{
return;
};
private:
int foo_;
};
int main()
{
void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
Gizmo g;
(g.*fn)(); // once you have the function pointer, you can call the function this way
bool b = fn;
// void* v = (void*)fn; // standard explicitly disallows this conversion
cout << hex << fn;
return 0;
}
Pragnę zauważyć, że moja debugger (MSVC9) jest w stanie powiedzieć mi rzeczywisty adres fizyczny funkcji Członka w czasie wykonywania, więc wiem, że musi być jakimś sposobem na uzyskanie tego adresu. Ale jestem pewien, że jest niezgodny, nieprzenośny i prawdopodobnie zawiera kod maszynowy. Gdybym szedł tą drogą, zacznę od wpisania adresu wskaźnika funkcji (np. &fn
), odrzucając go, aby anulować * i odejdę stamtąd. Wymagałoby to również znajomości wielkości wskaźników (różnych na różnych platformach).
Ale chciałbym zapytać, o ile można zamienić wskaźnik funkcji elementu na wartość bool i ocenić istnienie wskaźnika, dlaczego w prawdziwym kodzie potrzebny byłby adres?
Prawdopodobnie odpowiedź na ostatnie pytanie brzmi "tak, że mogę określić, czy jeden wskaźnik funkcji wskazuje na tę samą funkcję, co druga." Słusznie. Można porównać wskaźniki funkcyjne dla równości:
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
class Gizmo
{
public:
void DoTheThing()
{
return;
};
**void DoTheOtherThing()
{
return;
};**
private:
int foo_;
};
int main()
{
void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
Gizmo g;
(g.*fn)(); // once you have the function pointer, you can call the function this way
bool b = fn;
// void* v = (void*)fn; // standard explicitly disallows this conversion
cout << hex << fn;
**void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing;
bool same = fnOther == fn;
bool sameIsSame = fn == fn;**
return 0;
}
+1. Jedyną standardową konwersją stosowaną do wskaźnika do funkcji jest (z wyjątkiem konwersji l-wartość do-r) konwersja do 'bool'. W szczególności musisz wykonać 'reinterpret_cast', aby przekształcić' int (*)() 'na' void * '. – avakar
@avakar Czy istnieje jakiś dokument obejmujący zasady konwersji wskaźników funkcji? – ibread
Ostatecznym dokumentem byłby standard C++, sekcje 4 [konw.] I 5.2 [expr.post]. Standard nie jest bezpłatny, ale najnowszą wersję można pobrać tutaj: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf. Pamiętaj, że czytanie może być trudne, jeśli nie jesteś do tego przyzwyczajony. – avakar