 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Sascha T. Guest
|
Posted: Mon Oct 11, 2004 8:40 pm Post subject: ifndef/define in Header reicht nicht?!? |
|
|
Hi!
Der Newbie wieder...
Folgende Minimalsources:
/*****************************
ext.h
*****************************/
#ifndef _EXT_
#define _EXT_
extern const int a=8;
#endif
/*****************************
ext.cpp
*****************************/
#include "ext.h"
/*****************************
main.cpp
*****************************/
#include <iostream>
#include "ext.h"
using namespace std;
int main() {
int b=2;
cout << a << b << endl;
return 0;
}
$ g++ -c ext.cpp join.cc && g++ ext.o join.o -o join
führt zu:
join.o(.rodata+0x0): multiple definition of `a'
ext.o(.rodata+0x0): first defined here
Folgende Änderung führt zu einem compilefähigen Code:
/*****************************
ext.cpp
*****************************/
#ifndef _EXT_
#define _EXT_
#include "ext.h"
#endif
Aber das ist doch wohl nicht Sinn der Sache, oder? Ich dachte, eine
einzige Definition im Header sollte reichen...
Bin für alle Tips dankbar!
Gruss
--
Sascha T.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Mon Oct 11, 2004 10:05 pm Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Ich kann dir jetzt nicht helfen (es ist schon spät), aber das was du vor hast,
entspricht nicht ganz dem, was man üblichweiser macht.
Wenn du eine Headerdatei schreibst, dann kannst du blind folgendes Skellet benutzen:
#ifndef MY_CLASS_H
#define MY_CLASS_H
class MyClass {
};
#endif
Dadurch wird garantiert, dass du jeden Header nur einmal einbindest.
Das Problem bei dir scheint zu sein, dass du eine Variable als extern
deklarierst und ihr gleichzeitig einen wert zuweist. Das macht nur bedingt Sinn,
weil extern in etwa heißt "lieber Compiler ich gebe dir jetzt eine Variable
bekannt, die hier keine Speicher braucht, weil sie woanders (nämlich extern)
definiert ist".
Was soll den der Compiler anfangen, wenn du z.B. in einer Komiliereinheit schreibst:
extern const int x = 5;
und in der anderen
extern const int x = 17;
Die Variable existiert nur einmal (irgendwo extern - der linker kümmert sich
darum dass sie gefunden wird), aber eine gleichzeitige Initialiesierung ergibt
keinen Sinn, weil der Compiler hier ambivalente Werte zuweisen müsste.
Lösung ist (vermutlich), die Variable einmal zu definieren (dort, wo sie
tatsächlich existiert), dort dann auch mit einem Wert zu initialisieren und in
alle Kompiliereinheiten, die auf diese Variable zugreifen wollen, über die
Headerdatei,
extern const int x;
einzufügen.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Andreas Huennebeck Guest
|
Posted: Tue Oct 12, 2004 7:28 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Sascha T. wrote:
| Quote: | Folgende Minimalsources:
/*****************************
ext.h
*****************************/
#ifndef _EXT_
#define _EXT_
extern const int a=8;
#endif
|
lass das extern weg, das hat bei Konstanten nichts verloren.
Tschau
Andreas
--
Andreas Hünnebeck | email: [email]ah (AT) despammed (DOT) com[/email]
----- privat ---- | www : http://www.huennebeck-online.de
Fax/Anrufbeantworter: 0721/151-284301
GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Sascha T. Guest
|
Posted: Tue Oct 12, 2004 9:35 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Vielen Dank, hat sehr geholfen! Jetzt geht's.
Hab mir den Link durchgelesen, nur damit ich das richtig vestehe:
Es ist in C++ angebrachter, globale (und externe) Konstanten in Klassen
zu definieren? Das erinnert mich an einen Satz, den ich vor einigen Tagen
in einem STL Tutorial (von Phil Ottewel) über Strings in C gelesen habe:
"A member of the C++ standards commitee was allegedly told that if
strings didn't appear pretty darn quickly, then there was going to be a
lynching!"
Na, aber nichts für ungut, bin dankbar für jeden Hinweis auf guten
C++-Programmierstil!
Thanxs
ST
--
-----------------------------
E=mc^2 -> I really *mean* it!
-----------------------------
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Sascha T. Guest
|
Posted: Tue Oct 12, 2004 9:38 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Am Tue, 12 Oct 2004 00:05:07 +0200 schrieb Boris Glawe:
| Quote: | Dadurch wird garantiert, dass du jeden Header nur einmal einbindest.
|
Ja, genau das hatte ich vor.
| Quote: | ... weil extern in etwa heißt "lieber Compiler ich gebe dir jetzt eine
Variable bekannt, die hier keine Speicher braucht, weil sie woanders
(nämlich extern) definiert ist".
|
Ahhh, *diese* Sprache verstehe ich ;-)
Danke auch für die Hinweise,
Gruss
ST
--
-----------------------------
E=mc^2 -> I really *mean* it!
-----------------------------
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Markus Schaaf Guest
|
Posted: Tue Oct 12, 2004 10:07 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
"Sascha T." <saschat (AT) due-to-spam_this-mail-is-a-fake (DOT) fake> schrieb:
| Quote: | Am Tue, 12 Oct 2004 00:05:07 +0200 schrieb Boris Glawe:
... weil extern in etwa heißt "lieber Compiler ich gebe dir jetzt eine
Variable bekannt, die hier keine Speicher braucht, weil sie woanders
(nämlich extern) definiert ist".
Ahhh, *diese* Sprache verstehe ich
|
Ist aber falsch.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Sascha T. Guest
|
Posted: Tue Oct 12, 2004 11:20 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Am Tue, 12 Oct 2004 12:07:37 +0200 schrieb Markus Schaaf:
| Quote: | "Sascha T." <saschat (AT) due-to-spam_this-mail-is-a-fake (DOT) fake> schrieb:
Am Tue, 12 Oct 2004 00:05:07 +0200 schrieb Boris Glawe:
... weil extern in etwa heißt "lieber Compiler ich gebe dir jetzt eine
Variable bekannt, die hier keine Speicher braucht, weil sie woanders
(nämlich extern) definiert ist".
Ahhh, *diese* Sprache verstehe ich ;-)
Ist aber falsch.
|
Schade Eben dachte ich, ich hätte es kapiert ...
Gruss
ST
--
-----------------------------
E=mc^2 -> I really *mean* it!
-----------------------------
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Raymond Haeb Guest
|
Posted: Tue Oct 12, 2004 11:49 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Es begab sich, daß Sascha T. schrieb:
| Quote: | Es ist in C++ angebrachter, globale (und externe) Konstanten in Klassen
zu definieren?
|
Warum Klassen? Reichen da nicht namespaces für aus?
Raymond
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Tue Oct 12, 2004 1:24 pm Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Raymond Haeb wrote:
| Quote: | Es begab sich, daß Sascha T. schrieb:
Es ist in C++ angebrachter, globale (und externe) Konstanten in Klassen
zu definieren?
Warum Klassen? Reichen da nicht namespaces für aus?
|
Meistens ja, außer wenn
- die Konstante logisch eng mit einer Klasse verbunden ist
und nur in Verbindung mit ihr benutzt wird (dann kann man
auch überlegen, ob man sie vielleicht protected / private
macht; public nur, wenn sie auch im öffentlichen Interface
auftaucht),
- die Konstante von einem Template-Parameter abhängen soll
(man "traits class")
MfG
Falk
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Horst Kraemer Guest
|
Posted: Tue Oct 12, 2004 3:10 pm Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
"Sascha T." <spam-collector (AT) t-online (DOT) de> wrote:
| Quote: |
Hi!
Der Newbie wieder...
Folgende Minimalsources:
/*****************************
ext.h
*****************************/
#ifndef _EXT_
#define _EXT_
extern const int a=8;
#endif
/*****************************
ext.cpp
*****************************/
#include "ext.h"
/*****************************
main.cpp
*****************************/
#include
#include "ext.h"
using namespace std;
int main() {
int b=2;
cout << a << b << endl;
return 0;
}
$ g++ -c ext.cpp join.cc && g++ ext.o join.o -o join
führt zu:
join.o(.rodata+0x0): multiple definition of `a'
ext.o(.rodata+0x0): first defined here
Folgende Änderung führt zu einem compilefähigen Code:
/*****************************
ext.cpp
*****************************/
#ifndef _EXT_
#define _EXT_
#include "ext.h"
#endif
Aber das ist doch wohl nicht Sinn der Sache, oder? Ich dachte, eine
einzige Definition im Header sollte reichen...
Bin für alle Tips dankbar!
|
Ein sogenannter include-gard a la
// bla.h
#ifndef BLAH_H
#define BLAH_H
// Deklarationen
#endif
// ende bla.h
hat einzig und allein folgenden Zweck: Er verhindert, dass der Header
bla.h zweimal in *dieselbe* Quelldatei hineingezogen wird. Dies
betrifft Faelle wie diesen:
//a.h
#include "bla,h"
//irgendentwas
// ende a.h
//main.cpp
#include "bla.h"
#include "a.h"
....
// ende main.cpp
Da die Wirkung von #include "a.h" ja ist, dass der Text von a.h in der
Datei main,cpp an dieser Stelle erscheint und rekursiv durch das
#include "blah.h" in a.h wiederum dessen Text und durch das direkte
#include "blah,h" dieser Text noch einmal, findet der Compiler nach
dem Preprocessing den Inhalt von bla.h zweimal vor. Der include-gard
sorgt jetzt dafuer, dass das zweite Vorkommen und jedes weitere
Vorkommen des Inhalts von bla.h in main.cpp ignoriert wird.
Der include-gard kann und soll aber nicht verhindern, dass bla.h in
zwei verschiedenen Quelldateien hineingezogen wird. die beide bla.h
inkludieren und unabhaengig voneinander compiliert werden.
Dein Problem ist, dass durch das #include in zwei verschiedenen
Quelldateien Deines Projekts die Zeile
extern const int a=8;
in diesen zwei Quelldateien steht. Dies ist unzulaessig, da die
Initialisierung bewirkt, dass es sich hier um *Definitionen* von a
handelt. Es wird also versucht zweimal Speicher fuer dieselbe Variable
anzulegen.
Wenn Du wirklich eine globales const-Objekt namens a haben willst, so
musst Du die Initialisierung in der Header-Datei weglassen, also die
Zeile durch
extern const int a;
ersetzen und Deinem Projekt *zusaetzlich* eine Datei const.cpp mit dem
Inhalt
extern const int a=8;
hinzufuegen, oder in genau *eine* Quelldatei Deines Projekts (egal
welche) die Zeile
extern const int a=8;
einfuegen. Dann wird die Variable nur einmal *angelegt* und die
Deklarationen
extern const int a;
im Header beziehen sich dann alle automatisch auf *diese* einmalige
Definition und machen diese nur bekannt.
--
Horst
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Tue Oct 12, 2004 6:55 pm Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Sascha T. wrote:
| Quote: | Am Tue, 12 Oct 2004 12:07:37 +0200 schrieb Markus Schaaf:
"Sascha T." <saschat (AT) due-to-spam_this-mail-is-a-fake (DOT) fake> schrieb:
Am Tue, 12 Oct 2004 00:05:07 +0200 schrieb Boris Glawe:
... weil extern in etwa heißt "lieber Compiler ich gebe dir jetzt eine
Variable bekannt, die hier keine Speicher braucht, weil sie woanders
(nämlich extern) definiert ist".
Ahhh, *diese* Sprache verstehe ich ;-)
Ist aber falsch.
Schade Eben dachte ich, ich hätte es kapiert ...
|
Wir sind hier in einer Programmiersprachengruppe, wo auf exakte
Formulierungen Wert gelegt wird. Zum einen wäre die korrekte
Umschreibung "lieber Compiler, ich gebe dir jetzt eine Variable bekannt,
für die du *jetzt keinen Speicher allokieren musst*, weil sie woanders
(nämlich extern) definiert ist".
Außerdem bedeutet 'extern' noch, dass die Variable "external linkage"
hat, also von außerhalb der Übersetzungseinheit (=".cpp-Datei") sichtbar
ist - im Gegensatz zu einer static-Variable, die nur innerhalb der
Übersetzungseinheit sichtbar ist. Das muss auch so sein, denn wäre die
Variable von außen nicht sichtbar, wäre es schwierig, sie außerhalb zu
definieren.
Um die Sache zu verkomplizieren: mittels anonymer Namensräume kann man
Variablen erstellen, die zwar external linkage haben, aber dennoch nicht
von außen sichtbar sind. Und dann gibt es noch static-Variablen in
Klassen, die, wenn sie public sind, dennoch sichtbar sind. Aber das
kannst du ja erstmal ignorieren :)
Stefan
--
np: Wise Guys - Die Philosoffen
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Sascha T. Guest
|
Posted: Tue Oct 12, 2004 7:48 pm Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Zoink!!! Jetzt ist der Groschen dank deiner ausführlichen Hilfe gefallen!
Am Tue, 12 Oct 2004 17:10:54 +0200 schrieb Horst Kraemer:
| Quote: | hat einzig und allein folgenden Zweck: Er verhindert, dass der Header
bla.h zweimal in *dieselbe* Quelldatei hineingezogen wird. Dies
|
Genau *das* war mein Verständnisproblem. Ich dachte, der Include-gard
würde verhindern, dass bla.h zweimal *überhaupt* gelesen wird. So
macht natürlich alles einen Sinn!
Thanx auch für die restlichen Tipps!
Gruss
--
ST
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Wed Oct 13, 2004 12:01 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
| Quote: |
Wir sind hier in einer Programmiersprachengruppe, wo auf exakte
Formulierungen Wert gelegt wird. Zum einen wäre die korrekte
Umschreibung "lieber Compiler, ich gebe dir jetzt eine Variable bekannt,
für die du *jetzt keinen Speicher allokieren musst*, weil sie woanders
(nämlich extern) definiert ist".
|
Im üblichen Anwendungsfall, wird der Comiler für diese Variable auch niemals
Speicher anlegen. Das passiert an anderer Stelle, die mit der aktuellen
Compiliereinheit nichts zu tun hat (Ich weiß es gibt auch andere Fälle, in denen
man mit der Linkage rumtrickst und die aktuelle Compiliereinheit nicht
verlässt). Die Deklaration mit extern deutet darauf hin, dass diese anderswo
benutzte Variable nachher referenziert werden soll. Die Auflösung, wo diese
Variable tatsächlich ist, übernimmt der Linker.
Die Definition einer Variablendefinition ist, dass mit dem Bezeichner auch eine
Stück Speicher verbunden wird. Das ist bei einer Deklaration mit externnicht
der Fall. Deshalb weist man den Compiler an, überhaupt keine Speicher zu
reservieren - nicht jetzt und auch nicht nachher. Die Anweisung, Speicherzu
reservieren geschiegt (üblicherweise) in einer ander Compiliereinheit durch die
herkömmliche Variablendefinition.
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Markus Schaaf Guest
|
Posted: Wed Oct 13, 2004 12:17 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
"Stefan Reuther" <stefan.news (AT) arcor (DOT) de> schrieb:
| Quote: | Sascha T. wrote:
Am Tue, 12 Oct 2004 12:07:37 +0200 schrieb Markus Schaaf:
"Sascha T." <saschat (AT) due-to-spam_this-mail-is-a-fake (DOT) fake> schrieb:
Am Tue, 12 Oct 2004 00:05:07 +0200 schrieb Boris Glawe:
... weil extern in etwa heißt "lieber Compiler ich gebe dir jetzt eine
Variable bekannt, die hier keine Speicher braucht, weil sie woanders
(nämlich extern) definiert ist".
Ahhh, *diese* Sprache verstehe ich ;-)
Ist aber falsch.
Schade Eben dachte ich, ich hätte es kapiert ...
Wir sind hier in einer Programmiersprachengruppe, wo auf exakte
Formulierungen Wert gelegt wird. Zum einen wäre die korrekte
Umschreibung "lieber Compiler, ich gebe dir jetzt eine Variable bekannt,
für die du *jetzt keinen Speicher allokieren musst*, weil sie woanders
(nämlich extern) definiert ist".
|
Ähm. Der Ursprungsfall widerspricht dem gerade:
extern int const i = 3;
Das ist eine Definition, trotz »extern«, wegen der Initialisierung.
Vielleicht war das dem OP sogar klar, immerhin steht im Subject was
über Include-Guards (ein öfter anzutreffender Irrtum bezüglich
mehrerer Übersetzungseinheiten).
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Sascha T. Guest
|
Posted: Wed Oct 13, 2004 6:54 am Post subject: Re: ifndef/define in Header reicht nicht?!? |
|
|
Am Wed, 13 Oct 2004 02:17:46 +0200 schrieb Markus Schaaf:
| Quote: | Vielleicht war das dem OP sogar klar, immerhin steht im Subject was
über Include-Guards (ein öfter anzutreffender Irrtum bezüglich
mehrerer Übersetzungseinheiten).
|
Um weiteren Spekulationen vorzubeugen, hier mein Gedankengang:
1. Ich brauche eine Variable namens "a" vom Typ int:
int a;
2. Dieser soll der Wert "4" zugewiesen werden:
int a=4;
3. und nicht veränderbar sein:
const int a=4;
4. Ich möchte diese Konstante programmweit zur Verfügung haben, also
deklariere und definiere ich sie in einer Header-Datei und deklariere
sie als extern:
extern const int a = 4;
5. Da ich die Header-Datei in mehreren verschiedenen Dateien einlese,
jedoch "a" nur einmal deklarieren darf, versuche ich die multiple
Deklaration mit Hilfe des Include-Guards zu verhindern, indem dieser
dafür sorgen *soll* (wie ich fälschlicherweise dachte), das diese
Zeile nur einmal eingelesen wird:
#ifndef _BLA_
#define _BLA_
extern const int a = 4;
#endif
6. Dank Euerer Hinweise bin ich jetzt schlauer und weiss, dass der
Include-Guard lediglich verhindert, dass die Zeile mehrfach in die
*selbe* Datei eingelesen wird, uns somit programmweit natürlich
mehrfach deklariert wird.
Gruss
--
ST
-----------------------------
E=mc^2 -> I really *mean* it!
-----------------------------
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|