2014-03-05 6 views
6

Der Header common.h uns auf eine Klasse deklariert Test und eine Funktion ein Mitglied Funktionszeiger Empfang:Mitglied Funktionszeiger von vorne deklarierten Klasse

class Test; 

void func(const Test &t, int (Test::*f)() const, int x, int y); 

in der Quelldatei target.cpp definiere ich die Funktion, so dass

#include "common.h" 

void func(const Test &t, int (Test::*f)() const, int x, int y) { 
    std::cout << "f: " << (t.*f)() << ", x: " << x << ", y: " << y << std::endl; 
} 

In meiner Hauptdatei definiere ich die Klasse Test und verwenden Sie die Funktion func:

class Test { 
public: 
    int example() const { return 1; } 
}; 

#include "common.h" 

int main() { 
    Test t; 
    func(t, &Test::example, 0xaaaaaaaa, 0xbbbbbbbb); 
    return 0; 
} 

Offensichtlich ist dies ein wenig stinkend, da Zeiger auf Elementfunktionen manchmal mehr als ein einfacher Zeiger sind. Aber das resultierende Verhalten ist ein wenig überwältigend: Die angegebenen Parameter 0xaaaaaaaa und 0xbbbbbbbb werden nicht korrekt an die Funktion übergeben. Genauer gesagt interpretiert die Funktion func den gegebenen Stapel anders als die Daten, die der Aufrufer auf den Stapel geschoben hat. Die Größe f hängt davon ab, ob die Klasse nur vorwärts deklariert oder tatsächlich definiert ist. Die Ausgabe mit Visual Studio erstellt 2013:

f: 1, x: 0, y: 2130567168 

Ich dachte, wenn eine Vorwärts-Erklärung ausreicht, ist es wirklich spielt keine Rolle, ob eine Definition gibt es gegeben ist oder nicht.

+0

'0xaaaaaaaa' und' 0xbbbbbbbb' sind nicht als 'int' darstellbar (unter Windows-Aufrufkonventionen, siehe [MSDN] (http://msdn.microsoft.com/en-us/library/296az74e.aspx)). Die einschränkende Konvertierung ruft ein undefiniertes Verhalten hervor. Hast du es mit kleineren Nummern versucht? – Mankarse

+0

Ich wähle diese Werte, um sie klar auf meinem Stack zu sehen. Natürlich funktioniert es auch nicht, wenn Sie kleinere Werte wählen. Und ich dachte, die Eingrenzung wird während der Kompilierung vorgenommen, da diese Werte Literale sind und an ganzzahlige Werte gebunden sind. – phlipsy

+0

IMHO ist es nicht richtig, eine Funktion der forward deklarierten Klasse zu erhalten, da diese Funktion entweder virtuell sein kann oder nicht – borisbn

Antwort

4

Standardmäßig bevorzugt MSVC Geschwindigkeit über die Richtigkeit mit Zeigern zu Mitglied. Sie können es zwingen, gemäß dem Standard zu arbeiten, indem Sie das Compiler-Flag /vmg übergeben.

+0

Oh, das ist einfach großartig! Ich habe bei diesem Problem einen ganzen Tag verloren. – phlipsy

+0

@phlipsy Das gleiche ist mir passiert (d. H. Ich habe auch auf die harte Art von dieser Flagge erfahren). – Angew

+0

Haben Sie zusätzliche Informationen, Links usw. zu diesem Punkt? – phlipsy