Wird eine virtuelle Memberfunktion verwendet, wenn sie nicht rein ist?

8

C++03 3.2.2 ... Ein Objekt oder eine nicht überladene Funktion wird verwendet, wenn der Name in einem potenziell ausgewerteten Ausdruck erscheint. Eine virtuelle Memberfunktion wird verwendet, wenn sie nicht rein ist ...

Und dann später in 3.2.3 haben wir: Jedes Programm soll genau eine Definition von jeder nicht-inline Funktion oder Objekt enthalten, das in diesem Programm verwendet wird; keine Diagnose erforderlich. Die Definition kann explizit im Programm erscheinen, sie kann im Standard oder in einer benutzerdefinierten Bibliothek gefunden werden, oder (falls zutreffend) implizit definiert (siehe 12.1, 12.4 und 12.8). Eine Inline-Funktion muss in jeder Übersetzungseinheit definiert sein, in der sie verwendet wird.

Entlang der Zeilen, die ich gerade lese: Eine reine virtuelle Funktion wird nicht benutzt. Die ODR gilt nur für Funktionen, die verwendet werden. Bedeutet das nicht, dass das Folgende legal wäre? Ich vermute, die Antwort ist nein, das tut es nicht, aber dann verstehe ich nicht warum.

%Vor%     
Armen Tsirunyan 10.11.2010, 15:15
quelle

5 Antworten

11

Die beiden Klauseln schließen sich nicht gegenseitig aus. Dass eine virtuelle Funktion verwendet wird, wenn sie nicht rein ist, bedeutet nicht, dass das Gegenteil gilt. Wenn eine virtuelle Funktion rein ist, bedeutet das nicht, dass sie nicht notwendigerweise verwendet wird. Es kann immer noch verwendet werden, "wenn sein Name in einem potenziell ausgewerteten Ausdruck erscheint", wie in Ihrem Beispiel: A::f(); .

    
Charles Bailey 10.11.2010, 15:25
quelle
3

Dieser Code verletzt ODR. A :: f ist mehrfach definiert. Daher hat es UB.

Mehrfache Definitionen über Übersetzungseinheiten sind nur für das Folgende gemäß $ 3.2 / 5

zulässig
  

Es kann mehr als eine Definition geben   einer Klassenart (Klausel 9),   Aufzählungstyp (7.2), Inline   Funktion mit externer Verknüpfung   (7.1.2), Klassenvorlage (Abschnitt 14),   nicht statische Funktionsvorlage (14.5.5),   statisches Datenelement einer Klassenvorlage   (14.5.1.3), Elementfunktion einer Klasse   Vorlage (14.5.1.1) oder Vorlage   Spezialisierung für welche Vorlage   Parameter sind nicht angegeben (14.7,   14.5.4) in einem Programm vorausgesetzt, dass jede Definition in einer anderen erscheint   Übersetzungseinheit und stellte die   Definitionen erfüllen das Folgende   Anforderungen.

    
Chubsdad 10.11.2010 15:28
quelle
1

Wie @Charles Bailey darauf hingewiesen hat, wird Ihr A::f tatsächlich verwendet, obwohl es rein virtuell ist. Aber das ist neben dem Hauptpunkt.

Es ist nicht korrekt, dass die Eine-Definition-Regel nicht für Funktionen gilt, die nicht verwendet werden. Wir haben:

  

3.2p1 Keine Übersetzungseinheit darf mehr als eine Definition einer Variablen, Funktion, eines Klassentyps, eines Aufzählungstyps oder einer Vorlage enthalten.

     

3.2p3 Jedes Programm soll genau eine Definition jeder nichtlinearen Funktion oder eines Objekts enthalten, das in diesem Programm verwendet wird; keine Diagnose erforderlich.

Zusammengenommen scheinen diese Anforderungen zu implizieren, dass eine verwendete Funktion genau eine Definition haben muss, und eine unbenutzte Funktion (einschließlich einer rein virtuellen Funktion, die niemals explizit aufgerufen wird) kann entweder keine Definition oder eine einzelne Definition haben. In beiden Fällen machen mehrere Definitionen für eine Nicht-Inline-Funktion das Programm schlecht ausgebildet.

Zumindest bin ich mir ziemlich sicher, dass das die Absicht ist. Aber Sie können zu einem Loch in der Phrasierung sein, da ein sehr wörtliches Lesen nirgends sagt, dass mehrere verschiedene Definitionen der gleichen ungenutzten Funktion in verschiedenen Übersetzungseinheiten schlecht gebildet sind.

%Vor%     
aschepler 10.11.2010 15:50
quelle
1

Das ist verwandt, aber nicht zum Thema: Aus den Zitaten scheint es, dass es im Standard ein Loch gibt: Es sollte auch heißen, dass ein reiner virtueller Destruktor verwendet wird und dass er definiert werden muss; zumindest wenn es abgeleitete Klassenobjekte gibt, die zerstört werden, oder wenn ein Destruktor von solchen definiert ist, da der abgeleitete Klassendestruktor den Basisdestruktor aufrufen muss, geschieht dies implizit mit der qualifizierten :: id-Syntax. Die Definition solcher Destruktoren ist normalerweise trivial, kann aber nicht gelöscht werden und kann nicht erzeugt werden.

    
Yttrill 28.11.2010 03:51
quelle
0

[class.abstract]: "Eine reine virtuelle Funktion muss nur definiert werden, wenn sie mit oder mit (12.4) der qualifizierten-ID-Syntax (5.1) aufgerufen wird."

Ihr A::f wird von B::f aufgerufen, daher muss es eine einzelne Definition von A::f geben.

    
Steve M 10.11.2010 15:25
quelle