Wann muss ich .cpp-Dateien #einschließen?

Lesezeit: 3 Minuten

Eine meiner Hausaufgaben umfasst drei Dateien: LineType.h, LineType.cpp und Driver.cpp. Driver.cpp enthält die Methode main(), die eine von LineType.h und LineType.cpp definierte Klasse verwendet.

Auf meinem System beginnt Driver.cpp mit:

#include "LineType.h"
#include "LineType.cpp"
#include <iostream>

Und das Programm kompiliert und läuft perfekt, wenn ich es ausführe g++ Driver.cpp aus dem Projektverzeichnis über die Kommandozeile. Wenn mein Lehrer jedoch versucht, das Programm zu kompilieren (ich glaube, sie verwendet Eclipse), kann es nicht kompiliert werden. Nach einigem Hin und Her konnte sie das Problem ihrerseits beheben, indem sie eines der #includes aus Driver.cpp auskommentierte:

#include "LineType.h"
//#include "LineType.cpp"
#include <iostream>

Wenn ich versuche zu laufen g++ Driver.cpp In dieser bearbeiteten Datei beschwert sich mein Compiler über “Undefinierte Symbole für die Architektur”, was meines Erachtens bedeutet, dass er keine Definitionen für die aufgerufenen Klassen/Methoden finden kann.

Was machen mein Ausbilder und ich anders, um diesen Unterschied im Verhalten zu verursachen? Warum führt eine von meinem Compiler benötigte Zeile dazu, dass ihr Compiler fehlschlägt?

  • Anfänger sollten noch nie müssen Quelldateien enthalten. Stattdessen sollten Sie weiterlesen separate Zusammenstellung und Objektdateien und verlinken.

    – Irgendein Programmierer-Typ

    14. Juli 2017 um 20:04 Uhr

  • Du solltest nie #include eine cpp-Datei. Das Build-System Ihres Ausbilders macht eher so etwas g++ Driver.cpp LineType.cpp (obwohl es besser ist als das)

    – Justin

    14. Juli 2017 um 20:05 Uhr


Du solltest noch nie Quelldateien direkt einbinden.

Stattdessen sollten Sie alle Ihre Quelldateien in der g++ Befehl beim Kompilieren:

g++ Driver.cpp LineType.cpp MyOtherFile.cpp # etc...

  • Verwenden Sie für den faulen Anfänger g++ *.cpp und Sie erhalten jede cpp-Datei im Verzeichnis.

    – Justin

    14. Juli 2017 um 20:12 Uhr

Verwenden #include somefilename bedeutet, dass der Inhalt von irgendein Dateiname wird anstelle des include gesetzt.
Durch das Setzen #include "LineType.cpp" In Ihrer Driver.cpp-Datei stecken Sie alles in eine Datei und kompilieren dann mit g++ Driver.cpp funktioniert gut für Sie.
Als Ihr Kursleiter IDE zum Kompilieren verwendet hat, wurde es separat kompiliert und gelinkt. Also wurden Driver.cpp und LineType.cpp kompiliert. Beide Dateien enthalten Definitionen von LineType.cpp aufgrund dieses Include. Als es also um das Verlinken ging, hatte sie alles zweimal in LineType.cpp definiert und der Linker wusste nicht, was er tun sollte. Sie können mehrere Dateien gleichzeitig kompilieren und verknüpfen, indem Sie verwenden

g++ Driver.cpp LineType.cpp 

Oder verwenden Sie separate Kompilier- und Verknüpfungsbefehle

g++ -c Driver.cpp
g++ -c LineType.cpp

Welche Dateien erzeugen Driver.o und LineType.o. Dann können Sie sie miteinander kombinieren, indem Sie laufen

g++ Driver.o LineType.o

Ich persönlich rate dringend davon ab include Quelldaten. Aber Autor von diesem Artikel behauptet, dass das Einschließen von Quelldateien die Kompilierungszeit für große Projekte in Bestellungen verkürzen kann. Er nennt dies „Unity Builds“ und behauptet, dass der Ansatz in der Spielebranche weit verbreitet ist. Die Hauptidee von Unity Build besteht darin, die Anzahl der Module in einer Kompilierung zu reduzieren. So was:

my_unity_build_1.cpp:

#include "renderer.cpp"
#include "ui_elements.cpp"
#include "gameplay_code.cpp"
#include "character_AI.cpp"

my_unity_build_2.cpp:

#include "file_io.cpp"
#include "cat_dynamics.cpp"
#include "wobbly_bits.cpp"
#include "death_ray.cpp"

Weniger Module bedeuten weniger Duplizierung gemeinsamer Funktionen und weniger Codegenerierung. Module ermöglichen eine drastische Verkürzung der Kompilierzeit, sind aber immer noch nicht im Standard.

  • Unter Spieleprogrammierern (wie in jeder anderen Gruppe) gibt es eine gewisse (ähm) Religion. Hinter der Religion steckt oft etwas Wahres, aber auch eine Überakzeptanz von Dogmen. Wenn Sie beispielsweise vollständige Neuaufbauten gegenüber inkrementellen Builds bevorzugen oder komplexe Header (z. B. mit Vorlageninstanziierung), die in mehreren Kompilierungseinheiten enthalten sind, die Gesamtaufbauzeiten (nicht inkrementelle) erhöhen. Es wird manchmal behauptet, dass Unity-Builds Compiler-Optimierern helfen, aber dieses Argument wird durch moderne Toolchains geschwächt, die die Linkzeitoptimierung unterstützen.

    – Petrus

    14. Juli 2017 um 23:59 Uhr

1012940cookie-checkWann muss ich .cpp-Dateien #einschließen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy