Frage

Gibt es einen Grund, warum std::type_info angegeben ist polymorph zu sein? Der Destruktor wird angegeben virtuell zu sein (und es gibt einen Kommentar zu den Auswirkungen der „so dass es polymorph ist“ in dem Design und die Entwicklung von C ++). Ich kann nicht wirklich einen zwingenden Grund sehen, warum. Ich habe keine speziellen Anwendungsfall haben, ich habe mich nur gefragt, ob es jemals eine Begründung oder eine Geschichte dahinter war.


Hier einige Ideen, die ich komme mit und abgelehnt:

  1. Es ist ein Erweiterungspunkt - Implementierungen können Subklassen definieren und Programme könnten dann versuchen, eine dynamic_cast zu einem anderen std::type_info, Implementierung definiert abgeleiteten Typ. Dies ist möglicherweise der Grund, aber es scheint, dass es nur so einfach für Implementierungen eine Implementierung definiert Mitglied hinzuzufügen, die möglicherweise virtuell sein könnte. Programme Test für diese Erweiterungen wünschen würde notwendigerweise nicht tragbar sowieso.
  2. Es ist sicherzustellen, dass abgeleitete Typen richtig zerstört werden, wenn ein Basiszeiger deleteing. Aber es gibt keine Standard-abgeleiteten Typen, Benutzer nicht nützlich abgeleitete Typen definieren können, weil type_info keinen Standard öffentliche Bauer hat und so einen delete Zeiger type_infoing ist nie legal und tragbar. Und die abgeleiteten Typen sind nicht geeignet, da sie nicht konstruiert werden kann - die einzige verwende ich weiß, für eine solche nicht-konstruierbar abgeleiteten Typen bei der Umsetzung von Dingen wie der is_polymorphic Typ Merkmal ist
  3. .
  4. Es lässt die Möglichkeit offen von Metaklassen mit maßgeschneiderten Typen - jeder echte polymorphen class A eine abgeleitete „Metaklasse“ A__type_info bekommen würde, das ergibt sich aus type_info. Vielleicht so abgeleiteten Klassen könnten die Mitglieder dieses Anruf new A mit verschiedenen Konstruktorargumente in einer typsichere Art und Weise, und ähnlichem aus. Aber machen type_info polymorphen selbst macht eigentlich eine solche Idee im Grunde unmöglich zu implementieren, da Sie metaclasses für Ihre metaclasses, ad infinitum haben müsste, was ein Problem, wenn alle type_info Objekte statische Speicherdauer haben. Vielleicht abgesehen ist dies der Grund für die es polymorph.
  5. Es gibt einige Verwendung für die Anwendung RTTI-Funktionen (außer dynamic_cast) std::type_info selbst oder jemand dachte, dass es war nett, oder in Verlegenheit zu bringen, wenn type_info nicht polymorph war. Aber da gibt es keinen Standard abgeleiteten Typen, und keine andere Klassen in der Standardhierarchie, die man vernünftigerweise versuchen könnte, Querstich, die Frage ist: Was? Gibt es eine Verwendung für Ausdrücke wie typeid(std::type_info) == typeid(typeid(A))?
  6. Es ist, weil Implementierer einen eigenen abgeleiteten Typ schaffen (wie ich glaube GCC tut). Aber, warum es sich plagen Angabe? Auch wenn der destructor nicht als virtuelles angegeben wurde und ein Implementierer entschieden, dass es sein sollte, sicher, dass die Umsetzung könnte es virtuelle erklären, weil es nicht die Menge der erlaubten Operationen auf type_info ändert, so dass ein portables Programm, nicht in der Lage sein würde, den Unterschied zu erkennen.
  7. Es ist etwas mit Compiler mit teilweise kompatibel ABIs koexistieren zu tun, möglicherweise als Folge der dynamischen Verknüpfung. Vielleicht könnten Implementierer ihre eigene type_info Unterklasse erkennen (wie von einem anderen Anbieter zu einem Ursprung im Gegensatz) in einem tragbaren Weise, wenn type_info virtuellen sein war garantiert.

Die letzte ist die plausibelste im Moment für mich, aber es ist ziemlich schwach.

War es hilfreich?

Lösung

Ich gehe davon aus, dass es da für die Bequemlichkeit der Implementierer. Es erlaubt ihnen, erweitern type_info Klassen zu definieren, und löschen Sie sie durch Zeiger auf type_info beim Beenden des Programms, ohne in spezieller Compiler Magie zu bauen, die den richtigen destructor anrufen oder auf andere Weise durch Reifen springen.

  

sicher, dass die Umsetzung konnte   es virtuelle erklären, weil es nicht der Fall ist   Ändern Sie die Menge der erlaubten Operationen   auf type_info, so ein portables Programm   nicht in der Lage sein, das zu sagen,   Unterschied.

Ich glaube nicht, das ist wahr. Beachten Sie Folgendes:

#include <typeinfo>

struct A {
    int x;
};

struct B {
    int x;
};

int main() {
    const A *a1 = dynamic_cast<const A*>(&typeid(int));
    B b;
    const A *a2 = dynamic_cast<const A*>(&b);
}

Ob es sich um vernünftig oder nicht, die erste dynamische Umwandlung erlaubt (und auswertet auf einen Null-Zeiger), während die zweite dynamische Umwandlung ist nicht erlaubt. Also, wenn type_info im Standard definiert wurde den Standard-nicht-virtuellen Destruktor hat, aber eine Implementierung hinzugefügt, um eine virtuelle destructor, dann ein portables Programm könnte sagen, den Unterschied [*].

Es scheint mich einfacher, den virtuellen destructor im Standard zu setzen, als entweder:

a) legt einen Zettel in der Norm, dass, obwohl die Klassendefinition bedeutet, dass type_info keine virtuellen Funktionen hat, ist es erlaubt, einen virtuellen Destruktor zu haben.

b) die Menge der Programme bestimmen, die unterscheiden kann, ob type_info polymorph ist oder nicht, und verbieten sie alle. Sie können nicht sehr nützlich oder produktiv Programme sein, ich weiß es nicht, aber sie zu verbieten Sie haben mit einiger Standard-Sprache zu entwickeln, die die spezifischen Ausnahme beschreiben Sie machen die normalen Regeln.

Deshalb denke ich, dass der Standard der virtuellen destructor entweder zu Mandat hat, oder es zu verbieten. So dass es optional ist zu komplex (oder vielleicht soll ich sagen, ich denke, es wäre unnötig komplex beurteilt werden. Die Komplexität nie den Normenausschuß in Bereichen angehalten, wo es war die Mühe wert betrachtet ...)

Wenn es verboten wurde, aber dann eine Implementierung könnte:

  • fügen Sie einen virtuellen Destruktor zu einem gewissen abgeleiteten Klasse von type_info
  • leiten alle seine Typeinfo-Objekte von , die Klasse
  • verwenden, die intern als polymorphe Basisklasse für alles

, die die Situation lösen würde ich an der Spitze der Post beschrieben, und der statische Typ eines typeid Ausdruck würde noch const std::type_info sein, so dass es schwierig sein würde, für Implementierungen Erweiterungen zu definieren, wo Programme können dynamic_cast auf verschiedene Ziele, um zu sehen, welche Art von type_info Objekt, das sie in einem bestimmten Fall haben. Vielleicht ist der Standard zu hoffen, dass ermöglichen, obwohl eine Implementierung immer könnte eine Variante typeid mit einem anderen statischen Typ oder Garantie bieten, dass ein static_cast bis zu einem gewissen Erweiterungsklasse funktionieren wird, und dann das Programm dynamic_cast von dort lassen.

Insgesamt soweit ich das virtuelle destructor weiß, ist potentiell nützlich Implementierer, und es entfernt nicht jemand etwas anderes als gewinnen, dass wir nicht fragen, verbringen Zeit, warum es da ist; -)

[*] Eigentlich habe ich nicht bewiesen, dass. Ich habe gezeigt, dass ein illegales Programm würde, ceteris paribus, die Kompilierung. Aber eine Implementierung könnte vielleicht umgehen, indem sichergestellt wird, dass alle nicht gleich sind, und dass es nicht kompiliert. Boost des is_polymorphic ist nicht tragbar, so, während es für ein Programm zur Prüfung möglich ist, dass eine Klasse ist polymorpher, das sein sollte, kann es keine Möglichkeit für ein konformes Programm zu testen, dass eine Klasse nicht polymorpher hier ist, das sollte nicht. Ich denke aber, dass selbst wenn es unmöglich ist, das beweisen, um eine Zeile aus dem Standard zu entfernen, ist ziemlich viel Aufwand.

Andere Tipps

Die C ++ Standard sagt, dass typeid gibt ein Objekt vom Typ type_info, OR umsetzungs DEFINIERT Unterklasse davon. So ... Ich denke, das ist so ziemlich die Antwort. Also ich sehe nicht, warum Sie Ihre Punkte 1 und 2 ablehnen.

Absatz 5.2.8 Satz 1 der aktuellen C ++ Standard lautet:

  

Das Ergebnis eines typeid Ausdruck ist ein   L-Wert des statischen Typs const   std :: type_info (18.5.1) und dynamische   Typ const std :: type_info oder const   Name wobei Name ein ist   Implementierung definiert Klasse abgeleitet   von std :: type_info die Konserven   das Verhalten in 18.5.1.61 beschrieben)   Die Lebensdauer des Objekts bezeichnet   von dem L-Wert reicht bis zum Ende   das Programm. Unabhängig davon, ob die   destructor ist für die type_info genannt   Objekt am Ende des Programms ist,   nicht näher bezeichnet.

, was wiederum bedeutet, dass man den folgenden Code schreiben könnte, ist legal und in Ordnung: const type_info& x = typeid(expr);, die das erfordert type_info polymorphe

sein

Über die einfachste „global“ id Sie in C ++ haben kann ist ein Klassenname, und typeinfo bietet eine Möglichkeit, solche ids für Gleichheit zu vergleichen. Aber das Design ist so umständlich und begrenzt, dass Sie dann in einiger Wrapper-Klasse zu wickeln typeinfo benötigen, beispielsweise in der Lage seine Instanzen in einer Sammlung zu setzen. Andrei Alexandrescu tat, in seinem „Moderne C ++ Design“ und ich denke, dass typeinfo Wrapper Teil der Loki-Bibliothek ist; gibt es wahrscheinlich eine auch in Boost-; und es ist ziemlich einfach, Ihre eigene Rolle, z.B. finden Sie unter meine eigenen Wrapper .

Aber auch für eine solche Wrapper gibt es im Allgemeinen keine Notwendigkeit für einen virtuellen Destruktor in typeinfo.

Die Frage ist also nicht so viel „huh, warum gibt es eine virtuelle destructor“, sondern, wie ich es sehe „huh, warum ist das Design so nach hinten, umständlich und nicht direkt nutzbar“? Und ich würde, dass bis auf den Standardisierungsprozess setzen. Zum Beispiel iostreams ist nicht gerade Beispiele für hervorragendes Design, entweder; nicht etwas zu emulieren.

  

3 / Es lässt die Möglichkeit offen von Metaklassen mit maßgeschneiderten Typen - jeder echte polymorphen class A eine abgeleitete „Metaklasse“ A__type_info bekommen würde, das ergibt sich aus type_info. Vielleicht so abgeleiteten Klassen könnten die Mitglieder dieses Anruf new A mit verschiedenen Konstruktorargumente in einer typsichere Art und Weise, und ähnlichem aus. Aber machen type_info polymorphen selbst macht eigentlich eine solche Idee im Grunde unmöglich zu implementieren, da Sie metaclasses für Ihre metaclasses, ad infinitum haben müsste, was ein Problem, wenn alle type_info Objekte statische Speicherdauer haben. Vielleicht abgesehen ist dies der Grund für die es polymorph.

Clever ...

Wie auch immer, nicht einverstanden ich mit dieser Argumentation: solche Implementierung leicht Meta-Klassen für von type_info abgeleiteten Typen-ausschließen könnte, einschließlich type_info selbst

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top