2017-12-25 4 views
7

Zum BeispielC++ unterschiedliche Header-Dateien mit gleicher Implementierung der Klasse in mehreren Quelldateien

A. h

class Dummy { 
public: 
    Dummy() { std::cout << "a.h" << std::endl; } 
}; 

b.h

class Dummy { 
public: 
    Dummy() { std::cout << "b.h" << std::endl; } 
}; 

c.cc

umfassen
#include "a.h" 

void test() { 
    Dummy a; 
} 

d.cc

#include "b.h" 

int main() { 
    Dummy a; 
    return 0; 
} 

kompilieren Dann Quelldateien mit dem Befehl

g++ d.cc c.cc 

Ausgang ist

b.h 

aber mit dem Befehl

g++ c.cc d.cc 

Ausgang ist

a.h 

Meine Frage ist, warum keine multiple definition es Fehler ist und warum die Ausgabe auf Bestellung des Kompilierung hängt?

+0

Was ist 'A A'? Meinst du "Dummy"? – Mixhab

+1

Der Konstruktor von 'Dummy' ist in beiden Header-Dateien nicht gleich definiert. Das Ergebnis ist daher undefiniertes Verhalten, das ein Compiler nicht diagnostizieren muss. d.cc wird nicht kompiliert, da es keine Definition der Klasse A gibt. – Peter

+0

@Mixhab behoben, danke – Scy

Antwort

8

Ihr Programm hat ein undefiniertes Verhalten. Um das C++ Standard des Take zusammenfassen, hier ist [basic.def.odr/6] mit meinem Schwerpunkt:

kann es mehr als eine Definition eines Klasse-Typs, [...] in einem Programm vorgesehen, dass jede Definition erscheint in einer anderen Übersetzung Einheit und vorausgesetzt, die Definitionen erfüllen die folgenden Anforderungen: . Bei einer solchen Entität genannt D definiert in mehr als einer Übersetzungseinheit, dann

  • jede Definition von D der gleichen Sequenz von Tokens bestehen soll; und

  • [...]

[...] Wenn die Definitionen von D all diesen Anforderungen zu erfüllen, dann ist das Verhalten ist, als ob es eine einheitliche Definition von D. war Wenn Die Definitionen von D erfüllen diese Anforderungen nicht, dann ist das Verhalten undefiniert.

So beobachten Sie zwei unterschiedliche Verhaltensweisen. Tadellos akzeptabel, angesichts der Sprache gibt es keine Einschränkungen für das Verhalten, das Sie selbst sehen sollten. Sie haben den Vertrag verletzt, es gibt also keine Garantien.

Jetzt, was Sie sehen, ist praktisch gesehen nur GCC unter dem oben genannten Vertrag.Es geht davon aus, dass Sie es nicht verletzen würden (selbst wenn Sie das tun), und ignoriert einfach alle nachfolgenden Neudefinitionen von Dummy und/oder seinen Mitgliedern. Der erste "gewinnt".

3

Der Compiler erkennt keinen Multiple-Definition-Fehler, da und d.cc separate Übersetzungseinheiten sind. Sie werden getrennt voneinander verarbeitet; Jeder hat genau eine Definition von Dummy::Dummy Konstruktor.

Der Linker erkennt keinen Fehler mit mehreren Definitionen, da die Definition des Konstruktors Dummy::Dummy aus dem Header als Inline-Definition behandelt wird. Die Sprache erlaubt eine Inline-Definition in jeder Übersetzungseinheit, solange sie alle identisch sind. Normalerweise sind diese Definitionen identisch, weil sie alle aus derselben Headerdatei stammen. Der Standard erfordert jedoch, dass die Definitionen identisch sind, auch wenn sie aus verschiedenen Dateien stammen.

Wenn Ihr Programm gegen diese Regel verstößt, ist das Verhalten nicht definiert. Aus diesem Grund verhält sich Ihr Programm anders, je nachdem, wie Sie scheinbar die Reihenfolge der Übersetzungseinheiten während der Übersetzung ändern.

Verwandte Themen