Frage

C++03 3.2.2 ... Ein Objekt oder nicht-überladene Funktion wird verwendet, wenn der Name erscheint in einem potenziell bewertet Ausdruck. Eine virtuelle Member-Funktion wird verwendet, wenn es nicht rein ist ...

Und dann später in 3.2.3 haben wir: Jedes Programm muss enthält genau eine Definition jede Nicht-Inline-Funktion oder Objekt, das in diesem Programm verwendet wird; keine Diagnose erforderlich. Die Definition explizit im Programm erscheinen kann, kann es in der Standard- oder eine benutzerdefinierte Bibliothek, oder (wenn zutreffend) wird implizit definiert (siehe 12.1, 12.4 und 12.8) zu finden. Eine Inline-Funktion ist in jeder Übersetzungseinheit definiert werden, in dem sie verwendet wird.

Auf der Linie I Lesen bin: eine rein virtuelle Funktion nicht verwendet wird. Die ODR gilt nur für Funktionen, die verwendet werden. Ist dies nicht bedeuten, dass die folgenden legal wäre? Ich vermute, die Antwort ist nein, es funktioniert nicht, aber dann kann ich nicht verstehen, warum.

//x.h
struct A
{
   virtual void f() = 0;
};

//y.cpp
#include "x.h"
void A::f()
{
}

//z.cpp
#include "x.h"
#include <iostream>
void A::f()
{
   std::cout << "Hello" << std::endl;
}

//main.cpp
#include "x.h"
struct B:A
{
   virtual void f()
   {
      A::f();
   }
};

int main()
{
   A* p = new B;
   p->f();
}
War es hilfreich?

Lösung

Die beiden Klauseln sind nicht gegenseitig ausschließen. Dass eine virtuelle Funktion wird verwendet, wenn es nicht rein ist, bedeutet nicht, dass das Umgekehrte gilt. Wenn eine virtuelle Funktion rein ist, bedeutet es nicht, dass es nicht notwendigerweise verwendet. Es kann immer noch verwendet werden, wie in Ihrem Beispiel „wenn ihr Name in einem potentiell ausgewertete Ausdruck erscheint“. A::f();

Andere Tipps

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

Mehrere Definitionen für Übersetzungseinheiten sind nur für die folgenden erlaubt per $ 3.2 / 5

  

Es kann mehr als eine Definition sein   ein Klassentypen (Ziffer 9),   Aufzählungstyp (7.2), Inline   Funktion mit externer Bindung   (7.1.2), Klassenvorlage (Ziffer 14),   nicht-statische Funktion Vorlage (14.5.5),   statisches Datenelement einer Klasse template   (14.5.1.3), Elementfunktion einer Klasse   Schablone (14.5.1.1), oder die Vorlage   Spezialisierung, für die einige Vorlage   Parameter, die nicht angegeben sind (14.7,   14.5.4) in einem Programm vorgesehen, dass jede Definition befindet sich in einem unterschiedlichen   Übersetzungseinheit, und sofern die   Definitionen erfüllen die folgende   Anforderungen.

Wie @Charles Bailey wies darauf hin, Ihre A::f tatsächlich verwendet wird, obwohl es virtuelle rein ist. Aber das ist neben dem Hauptpunkt.

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

  

3.2p1 Keine Übersetzungseinheit muss folgende Angaben enthalten mehr als eine Definition einer Variablen, Funktion, Klassentyp, Aufzählungstyp oder eine Vorlage.

     

3.2p3 Jedes Programm wird genau eine Definition jeder Nicht-Inline-Funktion oder Objekts, das in diesem Programm verwendet wird; keine Diagnose erforderlich ist.

Zusammen stellen diese Anforderungen scheinen zu implizieren, dass eine gebrauchte Funktion muss genau eine Definition haben, und eine nicht verwendete Funktion (einschließlich einer rein virtuellen Funktion, die nie explizit genannt wird) kann entweder keine Definition oder eine einzige Definition haben. In jedem Fall machen mehr Definitionen für eine Nicht-Inline-Funktion des Programm schlecht ausgebildet ist.

Wenigstens bin ich ziemlich sicher, dass es die Absicht ist. Sie können aber in der Formulierung zu einem Loch sein auf, da eine sehr wörtliche Auslegung nicht überall sagen, dass mehrere unterschiedlichen Definitionen der gleichen nicht verwendeten Funktion in verschiedenen Übersetzungseinheiten sind schlecht ausgebildet ist.

// x.cpp
void f() {}
void g() {}

// y.cpp
#include <iostream>
void f() {
  std::cout << "Huh" << std::endl;
}
void h() {}

// z.cpp
void g();
void h();
int main() { 
  g();
  h();
  return 0;
}

Dies hängt aber vom Thema: aus den Zitaten es scheint, gibt es ein Loch in der Standard-Ordnung: es auch ein rein virtueller destructor wird verwendet, sagen sollte, und, dass es definiert werden muß; wenn es mindestens existieren keine abgeleiteten Klassenobjekten, die zerstört werden, oder wenn ein solcher destructor definiert ist, da die abgeleitete Klasse destructor die Basis Destruktoraufrufs muss, implizit tut sie dies mit der qualifizierten :: ID Syntax. Die Definition solcher Destruktoren ist in der Regel trivial, kann aber nicht elided werden und nicht erzeugt werden kann.

[class.abstract]: "Eine reine virtuelle Funktion muss nur dann, wenn mit genannt definiert werden, oder als ob mit (12.4), der qualifizierte-ID Syntax (5.1)."

Ihre A::f von B::f genannt wird, so muss es eine einheitliche Definition von A::f sein.

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