2010-01-25 9 views
20

In C++, ist mein Verständnis, dass virtuelle Funktion inline sein kann, aber im Allgemeinen wird der Hinweis auf Inline ignoriert. Es scheint, dass inline virtuelle Funktionen nicht zu viel Sinn machen.Inline virtuelle Funktion

Ist das richtig?

Kann jemand einen Fall angeben, in dem eine inline virtuelle Funktion gut ist?

+0

ich eine wirkliche Frage hier nicht ... –

+0

hallo, was tun Sie bedeuten? Ich habe das Problem nicht klar angesprochen? Das tut mir leid. – skydoor

+4

Inline-Funktionen sind niemals notwendig, daher wird es schwierig sein, Ihnen eine notwendige Inline-Funktion zu zeigen. – zneak

Antwort

15

Unter normalen Umständen wird eine virtuelle Funktion über einen Zeiger auf eine Funktion aufgerufen (die in der Klasse 'vtable' enthalten ist). In diesem Fall kann ein virtueller Funktionsaufruf nur dann inline generiert werden, wenn der Compiler den tatsächlichen Typ, für den die Funktion aufgerufen wird, statisch ermitteln kann und nicht nur die Klasse X oder etwas, das von X abgeleitet ist.

Die primäre Zeit, die eine inline virtuelle Funktion sinnvoll ist, ist, wenn Sie eine Performance-kritische Situation haben und wissen, dass eine Klasse häufig so verwendet wird, dass der Compiler den tatsächlichen Typ statisch ermitteln kann (und mindestens ein Ziel-Compiler optimiert die Aufruf über Zeiger).

+1

finde ich auch sehr kurze Funktionen, um klarer zu sein, wenn sie im Klassenkörper inline sind. – Omnifarious

+2

Die Frage bezieht sich auf das Schlüsselwort 'inline'. –

+0

Ich denke auch, wenn all Ihre virtuelle Funktion eine andere Funktion aufruft (was bei Mehrfachvererbung oder aus anderen Gründen passieren kann), kann der Compiler einfach das Thunking dafür in der vtable setzen. – Omnifarious

4

Sie können virtuelle Funktionen als Inline verwenden. Die Entscheidung, den Funktionsaufruf inline zu machen, wird nicht nur zur Kompilierzeit getroffen. Es könnte jederzeit zwischen Kompilierung zu Rutime sein. Sie können diesen Artikel von Herb Sutter beziehen. Inline Redux

37

Um diese Frage vollständig zu beantworten, muss man verstehen, dass die Eigenschaft virtual unabhängig auf die Funktion selbst und auf die Aufrufe dieser Funktion angewendet wird. Es gibt virtuelle und nicht-virtuelle Funktionen. Zu diesen Funktionen gibt es virtuelle und nicht virtuelle Aufrufe.

Das gleiche gilt für die Eigenschaft, inline zu sein. Es gibt Inline- und Nicht-Inline-Funktionen. Und es gibt inline und nicht inline Anrufe zu diesen Funktionen.

Diese Eigenschaften - virtual und inline - wenn sie auf die Funktion selbst angewendet werden, stehen sie nicht in Konflikt. Sie haben einfach keinen Grund und keine Chance zu Konflikten. Das einzige, was der Spezifizierer inline für die Funktion selbst ändert, ist, dass er die Eine-Definition-Regel für diese Funktion modifiziert: Die Funktion kann in mehreren Übersetzungseinheiten definiert werden (und muss in jeder Übersetzungseinheit definiert werden, in der sie verwendet wird). Die einzige Änderung virtual ist, dass die Klasse, die diese Funktion enthält, polymorph wird. Es hat keinen wirklichen Einfluss auf die Funktion selbst.

Also, es ist absolut kein Problem, eine Funktion virtual und inline zur gleichen Zeit zu deklarieren. Es gibt keine Grundlage für den Konflikt. Es ist absolut legal in C++ Sprache.

struct S { 
    virtual void foo(); 
}; 

inline void S::foo() // virtual inline function - OK, whatever 
{ 
} 

jedoch, wenn die Menschen diese Frage stellen, sind sie in der Regel in den Eigenschaften der Funktion nicht interessiert selbst, sondern in den Eigenschaften der an die Funktion Anrufe.

Das bestimmende Merkmal eines virtuellen Call ist, dass es während der Laufzeit aufgelöst wird, was bedeutet, dass es in der Regel unmöglich ist, echte virtuelle Anrufe Inline:

S *s = new SomeType; 
s->foo(); // virtual call, in general case cannot be inlined 

Wenn jedoch ein Anruf von selbst nicht virtuell (auch wenn es in eine virtuelle Funktion geht), ist inlining kein Problem:

S *s = new SomeType; 
s->S::foo(); // non-virtual call to a virtual function, can easily be inlined 

natürlich in einigen Fällen eine optimierende Compiler möglicherweise in der Lage das Ziel eines virtuellen Call bei der Kompilierung, um herauszufinden, und inline sogar einen solchen virtuellen Anruf. In einigen Fällen ist es einfach:

S ss; 
ss.foo(); // formally a virtual call, but in practice it can easily be inlined 

In einigen Fällen ist es komplizierter, aber immer noch machbar ist:

S *s = new S; 
s->foo(); // virtual call, but a clever compiler might be able 
      // to figure out that it can be inlined 
+0

Wie kannst du sagen, dass 'ss.foo();' formal ein virtueller Anruf ist? – Belloc

+0

@Belloc: Weil in C++ alle Aufrufe von virtuellen Funktionen "virtuelle Aufrufe" sind, d. H. Aufgelöst in Übereinstimmung mit dem dynamischen Typ des Objekts. Nichts in der Sprachspezifikation besagt, dass "ss.foo()" irgendwie speziell oder anders ist. Der einzige Aufruf, bei dem der "dynamische Typ" ignoriert wird, ist ein Aufruf mit einem qualifizierten Namen. – AnT

+0

Das kann ich [hier] nicht sehen (https://godbolt.org/g/PCjpqW). Die Disassemblierung für den Code zeigt, dass 'f-> bar()' wie erwartet ein virtueller Aufruf ist und 'd.bar()' ein nicht virtueller Aufruf ist. – Belloc

Verwandte Themen