2014-06-18 13 views
6

Bei der Verwendung von typeid für ein polymorphes Objekt, denke ich, das Objekt muss definiert werden (nicht nur eine Deklaration), weil typeid Betrieb die Informationen des Objekts bei Laufzeit erhalten muss. Hier ist mein Code:Wenn typid für ein polymorphes Objekt verwendet wird, muss es definiert werden?

#include <iostream> 
#include <typeinfo> 

class D { 
    virtual ~D() {} 
}; 
extern D d; 

int main() 
{ 
    std::cout << typeid(d).name() << std::endl; 
    std::cout << sizeof(d) << std::endl; 
} 

Und mit clang 3.4, bekam ich den Link Fehler:

undefined reference to `d'

Aber mit g++ 4.8.1, es funktioniert gut und ich erhielt das Ergebnis:

1D
8

Meine Frage :

  1. Welcher ist richtig?
  2. Wie implementiert g ++ typeid? Wie kann es die Information von einem polymorphen Objekt ohne Definition erhalten?
+2

Ich weiß nicht, welcher ist richtig, aber [g ++ Linker Fehler] (http://coliru.stacked-crooked.com/a/288ddd8f4e70f535) mit 'extern D & d'. Also vielleicht ist g ++ schlau genug, um herauszufinden, dass "d" Typ von "D" sein muss (vorausgesetzt es ist kein Zeiger oder Verweis) –

+0

@BryanChen Aber vielleicht nicht erlaubt durch den Standard ...? – songyuanyao

+1

Ich denke, der Grund, warum g ++ gut zu funktionieren scheint, ist der Typ von 'd'. Es ist * statisch * 'D', also weiß der Compiler den Typ von' d', und vielleicht hat g ++ den Code optimiert, um 'typeinfo' von' d' in Runtime zu bekommen. Wenn der Typ von "d" jedoch "D &" oder "D *" ist, kennt der Compiler seinen Typ ** in der Kompilierungszeit ** nicht, sodass der Code nicht optimiert werden kann. – ikh

Antwort

2

Von http://en.cppreference.com/w/cpp/language/typeid

a) If expression is a glvalue expression that identifies an object of a polymorphic type (that is, a class that declares or inherits at least one virtual function), the typeid expression evaluates the expression and then refers to the std::type_info object that represents the dynamic type of the expression. If the result of the evaluated expression is a null pointer, an exception of type std::bad_typeid or a type derived from std::bad_typeid is thrown.

Klingt wie Klirren 3.4 richtig ist.

aktualisieren

Der Standard sagt:

When typeid is applied to a glvalue expression whose type is a polymorphic class type (10.3), the result refers to a std::type_info object representing the type of the most derived object (1.8) (that is, the dynamic type) to which the glvalue refers. If the glvalue expression is obtained by applying the unary * operator to a pointer and the pointer is a null pointer value (4.10), the typeid expression throws the std::bad_typeid exception (18.7.3).

Aus der Sprache, die von cppreference.com verwendet ist etwas anders, aber es zeigt immer noch 3.4 sein Recht auf klirren.

+0

Der Ausdruck "wertet den Ausdruck aus" erscheint nicht im Standard. – Brian

+0

Wie deutet es an, dass es richtig ist? – Brian

+0

@Brian, wenn der Ausdruck zu einem polymorphen Typ ausgewertet wird, verstehe ich nicht, wie es für den Compiler möglich ist, die Typinformationen zur Kompilierzeit abzuleiten, die g ++ in der Lage ist, einige davon abzurücken. –