2010-01-17 18 views
12

j'ai quelque chose de semblable à cela dans mon code:tables virtuelles sur les classes anonymes

#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; 
} 

Je me attends ceci pour donner cette sortie:

ble: 1 
ble: 2 

et il le fait, lorsqu'il est compilé sous GCC (3.4.5 je crois).

Compiler et l'exécution de ce sous Visual Studio 2008 cependant, donne ceci:

ble: 2 
ble: 2 

Ce qui est intéressant, est que si je donne les noms des structs dérivés de base (struct s1 : public Base), il fonctionne correctement.

Quel comportement, le cas échéant, est correct? Est-ce que VS est juste en train de se montrer rancunier ou est-ce qu'il respecte la norme? Est-ce que je manque quelque chose de vital ici?

+1

Fonctionne comme attendu dans gcc.Pour être franc, je m'attendais à ne pas le compiler. –

+2

* VS conforme à la norme *? Ha ha ha ha ha ... – wallyk

+3

Hé, VC++ s'est beaucoup amélioré. – GManNickG

Répondre

2

Il est visible comment MSVC se trompe à cause des symboles de débogage. Il génère des noms temporaires pour les structures anonymes, respectivement Child::<unnamed-type-First> et Child::<unnamed-type-Second>. Il n'y a cependant qu'un seul vtable, il est nommé Child::<unnamed-tag>::'vftable' et les deux constructeurs l'utilisent. Le nom différent pour le vtable fait sûrement partie du bug.

Plusieurs bogues signalés sur connection.microsoft.com sont liés à des types anonymes, aucun d'entre eux ne l'ayant fait passer à l'état "must-fix". Pas celui que tu as trouvé, afaict. Peut-être que la solution de contournement est simplement trop simple.

7

Il semble que ce soit un bogue dans VS 2008, peut-être parce qu'il écrase ou ignore le vtable pour la première classe sans nom en faveur de la vtable pour la seconde puisque les noms internes sont identiques. (Lorsque vous en nommez un explicitement, les noms internes des vtables ne sont plus identiques.)

Pour autant que je puisse dire à partir de la norme, cela devrait fonctionner comme prévu et gcc a raison.

+0

(+1) explication bien écrite. –

1

Je peux confirmer qu'il s'agit d'un bogue connu dans le compilateur VC (et qu'il repose dans VC10); les deux classes anonymes partagent incorrectement un vtable.

Les structures anonymes sont et non partie de la norme C++.

Modifier: Les structures anonymes sont une sorte de terme ambigu. Cela peut vouloir dire deux choses:

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

    struct { 
     int c; 
    };  // 2 

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

1 est ce qui se passe ici, un meilleur nom que struct anonyme serait « struct sans nom ». Le type de structure lui-même n'a pas de nom, mais l'objet le fait (m_a).

2 est également connue sous le nom de structure anonyme et n'est pas légale C++. Il n'y a pas de nom d'objet, et l'idée est que vous pouvez accéder au champ 'c' directement sur les objets de type externe. Cela compile uniquement à cause d'une extension de compilateur dans Visual Studio (échouera sous/Za)

3 Les unions anonymes, en revanche, sont légales C++.

J'ai confondu les deux, parce qu'ici nous appelons # 1 une «structure anonyme», et des fils dans mon cerveau croisés aveC# 2.

+0

Les classes sans nom sont C++ standard et sont parfois appelées "anonyme" au lieu de "sans nom". –

+0

@Roger, Ce que j'ai dit est correct. J'ai dit anonyme ** structs **; Classes ** non anonymes **. Les classes anonymes font partie de la norme C++. Les structures anonymes sont une chose C, et ne font pas partie de C++ (bien qu'elles soient largement supportées par l'extension fournisseur, y compris VC). –

+0

"Une structure est une classe définie avec la structure de clé de classe ..." [9/4] ** Les structures sont des classes. ** –