2017-11-02 2 views
-2

Unter welchen Bedingungen wird die Klasse polymorph? 1. Ist es polymorph, wenn es vererbt wird und keine der Methoden überschrieben wird, sondern nur wenn sie ein virtuelles Schlüsselwort in der Signatur haben? 2. Ist es polymorph, wenn es keine Vererbung gibt und Methoden als virtuell deklariert werden?wird die Klasse polymorph, wenn sie nicht vererbt wird

Wird in obigen Fällen VTable erstellt?

+2

Sie finden http://en.cppreference.com/w/cpp/types/is_polymorphic und http://en.cppreference.com/w/cpp/language/object#Polymorphic_objects interessant. –

+0

@ FrançoisAndrieux und es schafft VTable immer wenn es polymorph ist? – debonair

+0

Bitte lesen Sie die Links. Von der zweiten: * "Innerhalb jedes polymorphen Objekts speichert die Implementierung zusätzliche Informationen (in jeder vorhandenen Implementierung ist es ein Zeiger, sofern nicht optimiert), der von virtuellen Funktionsaufrufen und von den RTTI-Funktionen verwendet wird ..." * –

Antwort

5

Eine Klasse ist polymorph, wenn sie mindestens eine virtuelle (eigene oder geerbte) Methode besitzt.


Wann ist es VTable schaffen?

Ok also lass uns zuerst den Elefanten aus dem Raum holen. Der Standard erfordert keine virtuellen Tabellen und lässt absichtlich die Methode zur Implementierung von dynamischem Polymorphismus offen. In diesem Fall definiert es nur Verhaltensregeln, schreibt jedoch keine Methode zur Implementierung dieses Verhaltens vor. Siehe Alternatives to vtable, Alternative virtual mechanism implementations? oder Comparison with alternatives. Sie sind eine interessante Lektüre. Nun, da der Elefant in der Praxis nicht im Raum ist, implementieren die meisten (wenn nicht alle) C++ - Compiler den Polymorphismus über den Vtables-Mechanismus.

Eine polymorphe Klasse wird eine virtuelle Tabelle haben. Und die Diskussion könnte hier leicht enden.


Es gibt jedoch einen interessanten (meist akademischen) Fall zu betrachten: virtuelle Vererbung ohne polymorphe Objekte.

Z. B .:

struct A {}; 
struct B : virtual A {}; 
struct C : virtual A {}; 

struct X : B, C { }; 

Keine der oben genannten Klassen (*) sind polymorph. I.e.

static_assert(!std::is_polymorphic<B>::value); 
static_assert(!std::is_polymorphic<C>::value); 
static_assert(!std::is_polymorphic<X>::value); 

weil wir keine virtuellen Methoden haben.

Die Frage ist jetzt, ob wir eine Vtable für oben genannten Klassen haben.

Und wieder ist die Implementierung der virtuellen Vererbung Implementierung definiert.

Und ehrlich gesagt kenne ich die Antwort darauf nicht.

Sowohl gcc und clang haben:

|   | 32 bit | 64 bit | 
| --------- | ------ | ------ | 
| sizeof(A) | 1  | 1  | 
| sizeof(B) | 4  | 8  | 
| sizeof(C) | 4  | 8  | 
| sizeof(X) | 8  | 16  | 

dem dieses B und C deuten darauf hin, enthalten jeweils einen Zeiger, der durch X vererbt werden. Von dem, woran ich mich erinnern kann, sind nicht Zeiger auf Vtables, sondern Zeiger (oder Offsets), die auf das Innere der Struktur zeigen, aber ich kann es nicht sicher sagen.


(*) Ich nutze diese Gelegenheit noch einmal zu erwähnen, dass ein Unternehmen mit dem struct erklärte Schlüsselwort eine Klasse ist.

+0

Interessante Dinge über die Größen, ich erwarte, dass die zusätzliche Größe auf die virtuelle Vererbung zurückzuführen ist - effektiv einen Zeiger auf A zu erstellen, habe ich mit Visual Studio 2017 überprüft. Die gleichen Ergebnisse für Ihr Beispiel. Weitere Untersuchungen legen nahe, dass bei dieser Implementierung der Zeiger auf die virtuelle Basis zurückzuführen ist und dass das Hinzufügen einer virtuellen Funktion die Größe durch einen zusätzlichen Zeiger erhöht (angenommen, dies ist ein v-Tabellenzeiger). Der Wechsel zu einer Y-Form aus dem Diamanten verringert die Größe wieder. – ROX

Verwandte Themen