2010-01-17 12 views
12

Ich habe etwas ähnliches wie dies in meinem Code:Virtuelle Tabellen auf anonyme Klassen

#include <iostream> 
#include <cstdlib> 

struct Base 
{ 
    virtual int Virtual() = 0; 
}; 

struct Child 
{ 
    struct : public Base 
    { 
    virtual int Virtual() { return 1; } 
    } First; 

    struct : public Base 
    { 
    virtual int Virtual() { return 2; } 
    } Second; 
}; 

int main() 
{ 
    Child child; 
    printf("ble: %i\n", ((Base*)&child.First)->Virtual()); 
    printf("ble: %i\n", ((Base*)&child.Second)->Virtual()); 

    system("PAUSE"); 
    return 0; 
} 

Ich würde erwarten, dass dies diese Ausgabe geben:

ble: 1 
ble: 2 

und es tut so, wenn sie unter kompiliert GCC (3.4.5 glaube ich).

Kompilieren und dies unter Visual Studio 2008 jedoch ausgeführt wird, ergibt dies:

ble: 2 
ble: 2 

Was interessant ist, das heißt, wenn ich den Grund abgeleiteten structs Namen (struct s1 : public Base) geben, es funktioniert einwandfrei.

Welches Verhalten ist, wenn überhaupt, korrekt? Ist VS nur zimperlich oder hält es sich an den Standard? Fehle ich etwas Vitales hier?

+1

Funktioniert wie erwartet in gcc.Um ehrlich zu sein, ich war es erwartet, dass es nicht kompilieren. –

+2

* VS Einhaltung des Standards *? Ha ha ha ha ha ... – wallyk

+3

Hey, VC++ ist viel besser geworden. – GManNickG

Antwort

2

Es ist sichtbar, wie MSVC es falsch von den Debugging-Symbolen bekommt. Es generiert temporäre Namen für die anonymen Strukturen bzw. Child::<unnamed-type-First> und Child::<unnamed-type-Second>. Es gibt jedoch nur eine vtable, sie heißt Child::<unnamed-tag>::'vftable' und beide Konstruktoren benutzen sie. Der andere Name für die Vtable ist sicherlich Teil des Fehlers.

Es gibt mehrere Fehler, die bei connection.microsoft.com gemeldet wurden und mit anonymen Typen in Zusammenhang stehen, von denen keiner jemals den Status "muss reparieren" festgelegt hat. Nicht die, die du gefunden hast, afaict. Vielleicht ist die Problemumgehung einfach zu einfach.

7

Es scheint, dies ist ein Fehler in VS 2008, möglicherweise weil es die Vtable für die erste unbenannte Klasse zugunsten der Vtable für die zweite überschreibt oder ignoriert, da die internen Namen identisch sind. (Wenn Sie einen explizit benennen, sind die internen Namen für die VTables nicht mehr identisch.)

Soweit ich aus dem Standard erkennen kann, sollte dies wie erwartet funktionieren und gcc ist richtig.

+0

(+1) gut geschrieben Erklärung. –

1

Ich kann bestätigen, dies ist ein bekannter Fehler im VC-Compiler (und es Repos in VC10); Die beiden anonymen Klassen teilen fälschlicherweise eine Vtable.

Anonyme Strukturen sind nicht Teil des C++ Standards.

Bearbeiten: Anonyme Strukturen sind eine Art mehrdeutiger Begriff. Es kann zwei Dinge bedeuten:

class outer 
{ 
public: 
    struct { 
     int a; 
     int b; 
    } m_a; // 1 

    struct { 
     int c; 
    };  // 2 

    union { 
     int d; 
     int e; 
    };  // 3 
}; 

1 ist das, was hier vor sich geht, ein besserer Name als anonyme Struktur würde „unbenannte struct“ sein. Der Strukturtyp selbst hat keinen Namen, aber das Objekt (m_a).

2 wird auch als anonyme Struktur bezeichnet und ist kein zulässiges C++. Es gibt keinen Objektnamen und man könnte auf das Feld 'c' direkt auf Objekte vom Typ outer zugreifen. Dies kompiliert nur wegen einer Compiler-Erweiterung in Visual Studio (wird unter/Za fehlschlagen)

3 Anonyme Unions dagegen sind legal C++.

Ich verwechselte die beiden, denn hier nennen wir # 1 eine "anonyme Struktur", und Drähte in meinem Gehirn mit # 2 gekreuzt.

+0

Unbenannte Klassen sind Standard-C++ und werden manchmal "anonym" anstelle von "unbenannt" genannt. –

+0

@Roger, was ich gesagt habe, ist richtig. Ich sagte anonyme ** Strukturen **; nicht anonym ** Klassen **. Anonyme Klassen sind Teil des C++ - Standards. Anonyme Strukturen sind eine C-Sache und nicht Teil von C++ (obwohl sie von vielen Herstellern unterstützt werden, einschließlich VC). –

+0

"Eine Struktur ist eine Klasse, die mit der Klassenschlüsselstruktur definiert ist ..." [9/4] ** Strukturen sind Klassen. ** –

Verwandte Themen