Stimmt es immer, dass die virtuelle Funktion in C ++ nicht eingebunden werden kann?

7

Es wird gesagt, dass virtuelle Funktionen nicht inline sein können. Ist es immer wahr, dass eine Funktion, die als virtuell deklariert ist, nirgendwo im Code inline oder nur in bestimmten Situationen anwendbar ist? (zB Aufruf einer Methode von einem Basiszeiger gegen eine aufrufende Methode für eine Referenz, etc.)

    
paseena 05.04.2011, 21:06
quelle

6 Antworten

8

Nein, virtuelle Funktionen können tatsächlich eingebunden werden. Virtuelle Verteilung wird nur verwendet, wenn eine virtuelle Methode polymorph (d. H. Auf einem Zeiger oder einer Referenz auf ein Objekt) aufgerufen wird. Wenn jedoch eine virtuelle Methode für ein Objekt value aufgerufen wird, wird der virtuelle Dispatch nicht verwendet und der Compiler kann nach eigenem Ermessen inline eingebunden werden.

    
ildjarn 05.04.2011, 21:16
quelle
6

Gegeben:

%Vor%

Polymorphie verwenden ( Wenn Sie foo() über pointer-to-T oder reference-to-T aufrufen)

%Vor%

Wenn ein Compiler weiß, dass T der einzige Knoten in seinem Vererbungsbaum ist, kann er auf die virtuellen Aufrufe verzichten und möglicherweise die Funktion inline machen. Dies ist jedoch ein unglaublich unwahrscheinliches Szenario, und ich bezweifle, dass es überhaupt möglich ist. In allen anderen Fällen ist Inlining aufgrund des Laufzeitversands nicht praktikabel.

Statischer Versand ( Wenn Sie foo() für ein Bog-Standardobjekt aufrufen)

%Vor%

In diesem Fall weiß der Compiler, dass der dynamische Typ von obj T ist, dass kein virtueller Versand erforderlich ist, und kann daher den Funktionscode bei Bedarf einfügen.

%Vor%

In diesem Fall kennt der Compiler den dynamischen Typ von obj nicht, aber er weiß, welche Funktion er aufrufen wird, weiß, dass er keinen virtuellen Dispatch benötigt, und kann daher den Funktionscode einfügen, wenn er dies möchte zu.

    
quelle
3

Eine virtuelle Elementfunktion ist im Grunde ein Zeiger auf eine Funktion, die auf die richtige Funktion verweist, die abhängig von den Implementierungen der Klassenhierarchie aufgerufen wird. (Beachten Sie, dass es kein Zeiger sein muss, aber es wird oft so implementiert, weil es die effizienteste Implementierung für diese Abstraktion zu sein scheint).

Das legt nahe, dass das Wissen, welche Funktion aufgerufen wird, nur zur Laufzeit festgelegt wird.

Wie wäre es also möglich, eine Funktion zu verknüpfen, die nur zur Laufzeit bekannt ist? Unmöglich.

  

Es sei denn, Sie haben einen JIT-Compiler :) -   the_drow

Wahr. Es ist nicht üblich und Sie könnten beim Booten etwas Leistung verlieren, aber immer noch wahr.

    
Klaim 05.04.2011 21:10
quelle
2

Objekte, die auf dem Stack oder innerhalb von Klassen deklariert sind, benötigen zum Beispiel keinen dynamischen Dispatch für ihre virtuellen Funktionen, die aufgerufen werden, weil der Compiler die Typen aller Objekte auf dem Stack kennt, also grundsätzlich jeden Wert. Die Verteilung virtueller Funktionen erfolgt nur über Zeiger oder Referenzen.

    
Puppy 05.04.2011 21:17
quelle
1

Wenn Optimierungen betroffen sind, ist sehr wenig immer wahr. Wenn der Compiler den tatsächlichen Typ eines Objekts nicht erkennen kann, müssen virtuelle Funktionen im Allgemeinen zur Laufzeit aufgelöst werden. Wenn Sie eine tatsächliche Instanz haben (Class versus Class & amp;), kann der Compiler sicher sein. Wenn Sie eine Referenz haben, muss sie raten; Wenn die aufrufende Funktion selbst inline ist, kann sie den statischen Typ auf diese Weise identifizieren oder nicht.

Beachten Sie, dass in diesem Fall kein Unterschied zwischen einem Zeiger und einer Referenz besteht. In beiden Fällen erhalten Sie Laufzeitpolymorphismus.

    
Dennis Zickefoose 05.04.2011 21:18
quelle
0

Virtuelle Funktionen (Methoden) können eingebunden werden. Denken Sie daran, dass das Schlüsselwort inline ein Vorschlag für den Compiler ist und keine Voraussetzung.

Das Einfügen von Code ähnelt dem Einfügen der Funktion, wie sie in der ausführbaren Datei benötigt wird. Eine eigenständige Funktion wird nicht erstellt.

Wenn es Zeiger auf eine Inline-Funktion gibt (intern vom Compiler oder extern vom Programmierer), darf das Inlining nicht verwendet werden. Es muss eine Instanz einer Inlining-Funktion geben, wenn Zeiger darauf stehen. Der Compiler kann den Code frei einbinden, aber es muss eine Instanz an einer statischen (festen) Position vorhanden sein, um die Zeiger zu erfüllen.

Mein Vorschlag ist es, einfache, weniger als 5 Zeilen Code, Methoden ohne einen Profiler zu inline. Denken Sie daran, dass beim Inlining normalerweise Code in eine Header-Datei eingefügt wird. Wenn der Code der Methode geändert wird, müssen alle Übersetzungseinheiten, die von der Headerdatei abhängig sind, neu erstellt werden. Dies könnte in großen Systemen teuer sein. Im Allgemeinen sollten große Codeabschnitte nur inline nachdem validiert werden und nur um die Effizienz zu verbessern, wie vom Profiler vorgegeben.

    
Thomas Matthews 05.04.2011 21:39
quelle