class::*



  • Hallo,

    ich habe in einem Forum folgenden Code gesehen:

    class D
    {
    
    };
    
    class C
    {
    public:
    	char szPointerSize_0x4; // 4
    };
    
    class B : public C, public D // Size would only be 0x4 with 1 inherited class
    {
    public:
    	char szPointerSize_0x8; // 8
    };
    
    class A : virtual public B // Size would only be 0x8 if it I removed virtual
    {
    public:
    	char szPointerSize_0xC; // 12
    };
    
    int main()
    {
    	size_t APtr = sizeof(unsigned long(A::*)());
    	size_t BPtr = sizeof(unsigned long(B::*)());
    	size_t CPtr = sizeof(unsigned long(C::*)());
    
    	printf("A: %d\nB: %d\n C: %d\n", APtr, BPtr, CPtr);
    
    	return 0;
    }
    

    Dabei geht es um die Größe von "member function pointers". Kann mir jemand erklären, warum da 4, 8, 12 rauskommt? Ich denke das klärt sich von selbst, wenn mir jemand erklärt, was "unsigned long(A::*)()" macht. 😕

    greetz KN4CK3R



  • Weil Member Function Pointers unter MSVC broken sind. Der Standard sagt in 5.2.10.10, dass _alle_ mfps ineinander umwandelbar sein müssen, auch wenn der Aufruf undefiniert ist. Das impliziert, dass die Dinger die selbe Größe haben müssen (Da Rückumwandlungen wieder den ursprünglichen mfp ergeben sollen).

    Unter GCC dürfte für alle 8 rauskommen, somit standardkonform.


  • Mod

    Kellerautomat schrieb:

    Der Standard sagt in 5.2.10.10, dass _alle_ mfps ineinander umwandelbar sein müssen, auch wenn der Aufruf undefiniert ist. Das impliziert, dass die Dinger die selbe Größe haben müssen (Da Rückumwandlungen wieder den ursprünglichen mfp ergeben sollen).

    Das ist ein Grund. Der andere liegt darin, dass Zeiger auf Member(-funktionen) für noch nicht definierte Klassen gebildet werden können. Ändert man das Beispiel etwas ab

    class A;
    unsigned long(A::*foo)();
    
    ..
    class A : virtual public B
    ..
        size_t APtr = sizeof(foo);
    

    wird das Problem noch auf andere Weise deutlich.

    Bei MSVC muss man solche Konstrukte also entweder vermeiden oder besser mit geeigneten Compileroptionen (/vmx oder so ähnlich, wenn mich mein Gedächtnis nicht täuscht) arbeiten.



  • was bedeutet denn A::*?

    greetz KN4CK3R


  • Mod

    KN4CK3R schrieb:

    was bedeutet denn A::*?

    😕 Das ist ein Pointer auf eine Memberfunktion. Also das worum sich dein ganzer Thread dreht.

    Genauer:

    unsigned long(A::*)()
    

    Das ist ein Zeiger auf eine Memberfunktion der Klasse A, die keine Parameter annimmt und einen unsigned long zurück gibt.

    Vielleicht ist es so klarer:

    unsigned long(A::*my_pointer)();
    

    Dies definiert my_pointer als einen Zeiger auf eine Memberfunktion der Klasse A, die keine Parameter annimmt und einen unsigned long zurück gibt.

    Da oben keine Variablen definiert wurden, sondern die Größe dieser Typen gesucht wurde, wurde auch kein Name für den Pointer angegeben.



  • ok danke
    mir war nicht klar, dass man da einfach deb Namen weglassen kann

    greetz KN4CK3R


  • Mod

    KN4CK3R schrieb:

    ok danke
    mir war nicht klar, dass man da einfach deb Namen weglassen kann

    Das ist wie der Unterschied zwischen

    sizeof(int);
    

    und

    int i;
    

Anmelden zum Antworten