003
19.03.2009, 22:06 Uhr
0xdeadbeef
Gott (Operator)
|
Du kannst nicht die gesamte Definition einer Funktion in den Header packen, das fliegt dir auseinander, sobald du den Header mehr als einmal einbindest - #include ist ja einfache Textersetzung, das heißt, der Compiler kompilierte in dem Fall die Funktion zweimal, und der Linker wüsste danach nicht, welches der beiden Kompilate er verwenden sollte.
In den Header kommt lediglich die Deklaration, und die ist in beiden Fällen gleich. Sie muss gleich sein, denn der verwendende Code erwartet das gleiche Interface. Dementsprechend macht es wenig Sinn, ein #ifdef um #includes zu setzen.
Ich habe im Beispiel oben get_a in Deklaration und Definition aufgeteilt - Deklaration im Header, wie üblich, der dann auch von der main.cpp eingebunden wird, und Definition mit #ifdefs in einer eigenen Übersetzungseinheit. Welcher Code am Ende genommen wird, hängt davon ab, ob MEIN_FLAG bei der Kompilierung von get_a.cpp definiert ist oder nicht.
Wenn sich der Code der beiden get_a-Funktionen komplett unterscheidet, kann es aber Sinn machen, die beiden Varianten komplett voneinander zu trennen. Etwa so:
C++: |
// get_a_2.cpp #include "get_a.hpp"
int get_a() { return 2; }
|
C++: |
// get_a_3.cpp #include "get_a.hpp"
int get_a() { return 3; }
|
und dann im Build-System zu unterscheiden. Für eine Makefile beispielsweise:
make: |
#!/usr/bin/make
OBJS = main.o get_a_2.o ifeq ($(VARIANTE),3) OBJS = main.o get_a_3.o endif
program: $(OBJS) $(CXX) $(CXXFLAGS) -o $@ $<
|
und dann per
kompilieren, falls get_a_3.cpp verwendet werden soll.
Außerdem wäre eine Entscheidung zur Laufzeit unter Verwendung eines Funktionszeigers oder gar eine Plugin-Architektur mit shared objects denkbar. -- Einfachheit ist Voraussetzung für Zuverlässigkeit. -- Edsger Wybe Dijkstra |