2013-04-17 17 views
9

Załóżmy, że mamy klasy AO sizeof z funkcji członka klasy wskaźnik

class A; 

i te typedefs

typedef void (A::*a_func_ptr)(void); 
typedef void (*func_ptr)(void); 

Moje pytanie brzmi dlaczego sizeof (a_func_ptr) zwraca 16, podczas gdy sizeof (func_ptr) zwraca 4 (jak w przypadku dowolnego wskaźnika w systemie x86)?

Na przykład

int main(int argc, char *argv[]) 
{ 
    int a = sizeof(a_func_ptr); 
    int b = sizeof(func_ptr); 
} 
+5

To [z tego powodu] (http://stackoverflow.com/a/13875868/335858). – dasblinkenlight

Odpowiedz

8

Moje pytanie brzmi dlaczego sizeof (a_func_ptr) zwraca 16, podczas gdy sizeof (func_ptr) zwraca 4 (podobnie jak w przypadku wskaźnika w systemie x86)?

Ponieważ wskaźniki do członków są realizowane inaczej. One są nie wskaźników pod maską. Niektóre kompilatory, takie jak MSVC, implementują je jako struct z więcej niż jednym elementem.

Przeczytaj ciekawy artykuł:

Należy zauważyć, że w niektórych kompilatorów, mogą mieć taki sam rozmiar. Najważniejsze jest to, że są zależne od kompilatora.

1

Funkcja klasy "wskaźnik do członka" nie zawiera "dokładnego adresu", jak ma to miejsce w przypadku zwykłego wskaźnika. Przechowuje więcej informacji niż zwykły wskaźnik funkcji.

Tak więc, gdy używasz sizeof do zmierzenia rozmiaru funkcji wskaźnika do elementu klasy, nie powinieneś oczekiwać, że będzie on miał taki sam rozmiar jak zwykły wskaźnik funkcji.

+0

Metoda, w przeciwieństwie do elementu danych, jest współużytkowana przez wszystkie instancje klasy, więc nie może mieć przesunięcia w układzie klasy. Czy też miałeś na myśli to, że wskaźnik do członka musi dodatkowo przechowywać wskaźnik "ten" oprócz adresu metody? – syam

+0

@syam co próbowałem powiedzieć, że wskaźnik do funkcji członka przechowuje więcej informacji niż zwykłe wskaźniki funkcji. To wyobrażam sobie, że część może wprowadzać w błąd, usuniemy ją. – taocp

0

Chociaż wskaźników funkcji w C i C++ mogą być realizowane jako proste adresów, tak że zwykle sizeof (Fx) == sizeof (void *), członek wskaźniki w C++ są często realizowane jako "wskaźniki Tłuszcz" zwykle dwa lub trzykrotność wielkości prostego wskaźnika funkcji w celu obsłużenia z dziedzicznym dziedziczeniem.

Źródło: Wikipedia

Ten SO answer offers additional information.

1

Rozważmy następujący:

#include <iostream> 

class A { 
public: 
    virtual void foo(){ std::cout << "A::foo" << std::endl; } 
    void bar(){ std::cout << "A::bar" << std::endl; } 
}; 

class B : public A { 
public: 
    void foo(){ std::cout << "B::foo" << std::endl; } 
    void bar(){ std::cout << "B::bar" << std::endl; } 
}; 

int main() { 
    a_func_ptr f = &A::foo; 
    a_func_ptr g = &A::bar; 
    B b; 
    A a; 
    (b.*f)(); 
    (b.*g)(); 
    (a.*f)(); 
    (a.*g)(); 
} 

wyjściowa:

B::foo 
A::bar 
A::foo 
A::bar 

Oba wskaźniki są członkami tego samego typu, ale zarówno prawidłowo kierowane połączenia w każdych przypadkach.

Jakoś wygenerowany programem musi wiedzieć gdy wskaźnik do metody jest rzeczywiście prosta metoda lub wirtualny. Zatem reprezentacja środowiska wykonawczego wskaźnika metody musi zawierać więcej informacji, aby obsłużyć drugi przypadek.

Uwaga: rozmiar wydaje się zależny od implementacji (otrzymuję 8 w moim systemie).

+0

brak aliasu "a_func_ptr" - dlaczego przekazujesz nieobsługiwany kod? – rikimaru2013

Powiązane problemy