Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
02.05.2002, 20:05
Leviathan



eine frage zu c++:

erstellt man im microsoft-kompiler mit dem assistenten eine neue klasse so wird deren deklaration in eine headerdatei geschrieben und deren implementation ein eine .cpp-datei.

nun die frage:
wie muss ich das machen, um eine globale funktion auf header und implementationsdatei zu verteilen?

simples beispiel (gibt das maximum zweier doubles zurück):

Quellcode:
//deklaration / prototyp
double max(double a,double b);

//implementation
double max(double a,double b)
{
    return a>b?a:b;
}

so, die deklaration soll in eine headerdatei, die implementation in eine .cpp datei. wie genau muss ich die präprozessoranweisungen setzen, damit das korrent verarbeitet wird?

ich hoffe mal ihr versteht die frage.

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds


Dieser Beitrag wurde am 02.05.2002 um 20:06 von Leviathan bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
001
02.05.2002, 21:11
Kriz



Quellcode:/*** Headerdatei ***/

double max(double, double);

// oder

double max(double a, double b);

/*** Sourcedatei ***/

#include "headerdatei.h"

double max(double a, double b)
{
    return a>b?a:b;
}

Das #include von prototyphaltigen Headerdateien muß immer VOR der Definition der jeweiligen Prototypen erfolgen.

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
002
02.05.2002, 21:44
Leviathan



danke schonmal dafür.
aber noch eine frage:
was muss ich dann im hauptprogramm inkludieren, die .h oder die .cpp-datei?so sieht es nach der .cpp-datei aus.

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche
003
02.05.2002, 22:18
Kriz



Einbinden kannst du nur Headerdateien:

<headerdatei.h> // Datei liegt im Standard-Headerverzeichnis
"headerdatei.h" // Datei liegt im selben Verzeichnis wie die Quelldatei
"C:\\trallalla\\headerdatei.h" // Datei liegt im Verzeichnis C:\\trallalla
"..\headerdatei.h" // Datei liegt ein Verzeichnis höher als die Quelldatei

Das Hauptprogramm an sich gibt es nicht. Es gibt nur die Hauptquelltextdatei, wo die Funktion main() ist. Alle möglicherweise anderen Quelltextdateien sind zusätzliche Module, die durch VC++ mitkompiliert werden, sobald sie im aktuellen Projekt mit drin sind.

Das könnte beispielsweise so aussehen:

main.cpp // Hauptquelltextdatei mit der Funktion main()

modul_1.cpp // Quelltextdatei
modul_2.cpp // dito
...
modul_n.cpp // dito

modul_1.h // Headerdatei
modul_2.h // dito
...
modul_n.h // dito

Dabei ist es egal, welche Quelltextdatei welche Headerdatei einbindet. Allerdings sollte man inhaltlich zusammengehörige Quelltext- und Headerdateien namentlich auch gleich benennen, dann weiß man sofort, wer zu wem gehört.

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
004
02.05.2002, 22:27
Leviathan



danke nochmal, aber:
man kann jede beliebige datei einbinden, die c/c++ code im ascii oder ansi-code enthält, die extension ist dabei egal. jedenfalls sieht es msvc++6.0 so, was der iso-standart dazu sagt weiss ich nicht.

nehmen wir mal folgendes hauptprogramm zu obigem beispiel:
(obiger code ist in max.h (prototyp) und in max.cpp (implementation))

Quellcode:
//testprogramm.cpp
#include<iostream>
#include"max.h"    //oder muss hier #include"max.cpp" hin?

main()
{
    cout<<max(7,9)<<endl;
}


(ich weiss, dass das sinlos ist, aber egal)
wie muss es jetzt lauten? und vor allen dingen: was sind vorkompilierte header .pch bei msvc++ 6.0? irgendwie hatte ich den fehler, dass der vorkompilierte header nicht gefunden wurde. irgentwie blicke ich da im moment nicht durch.

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche
005
03.05.2002, 01:38
Kriz



Ok, nochmal von vorne:

Du hast eine Quelldatei, in der die Funktion main() drinsteht. Diese Quelldatei kann sowohl alles beinhalten, was dein Programm braucht (inkl. aller Klassen und Funktionen und weiß der Geier was) oder du teilst alle Dinge nach einer gewissen, logischen Trennung auf. Das nennt man dann Modularisierung. Man teilt ein großes, komplexes Programm auf in kleine, übersichtliche Module.

In C/C++ realisiert man diese Module mit jeweils einem Pärchen aus einer Headerdatei und einer Quelldatei, die diese Headerdatei einbindet. In der Headerdatei stehen die Prototypen und Definitionen aller Dinge, die in der dazugehörigen Quelldatei deklariert werden.

In deinem Falle hättest du dann praktisch die Hauptquelldatei mit main() und ein Modul, daß wir mal "Maximum" nennen wollen. "Maximum" ist dabei ein imaginärer Name, der nichts mit der eigentlichen Implementierung zu tun hat. Aber da wir von einem Modul "Maximum" sprechen, wollen wir auch alle mit dem Modul verbundenen Dateien 'maximum' nennen.

Fangen wir an mit dem Modul "Maximum". Wie gesagt besteht es aus Header- und Quelldatei, stellt also in sich selber ein eigenes System dar, unabhängig von der Hauptquelldatei! Der einzige Unterschied zur Hauptquelldatei liegt darin, daß das Modul "Maximum" nicht alleine lauffähig ist, da es keine main() Funktion besitzt. Erst wenn auch die Hauptquelldatei die Headerdatei des Moduls einbindet, ist das Modul lauffähig! Die Modul-Headerdatei nennen wir 'maximum.h' und die dazugehörige Modul-Quelldatei 'maximum.cpp'.

Nun gut, die Implementierung des Moduls lautet dann so:
Quellcode:// Modul "Maximum" - Headerdatei maximum.h
// Prototyp der Funktion max()
double max(double, double);

Und nun die dazu passende Quelldatei:
Quellcode:// Modul "Maximum" - Quelldatei maximum.cpp
// Erfordert die Headerdatei maximum.h
#include "maximum.h"
// Definition der Funktion max()
double max(double a, double b)
{
    return a>b?a:b;
}

Damit wäre das Modul Maximum abgeschlossen. Du kannst es nun völlig unabhängig von allen anderen Modulen und von der Hauptquelldatei kompilieren. Das Modul ist nur eben nicht lauffähig.

Das erledigen wir nun mit der Hauptquelldatei, die wir mal main.cpp nennen:
Quellcode:// Hauptdatei - main.cpp
#include <iostream.h>
// Erfordert für die Funktion max() aus dem Modul "Maximum" die Headerdatei maximum.h
#include "maximum.h"
// Ab hier ist max() nun global bekannt in main.cpp!!!
void main(void)
{
    double x = 4.656,
           y = 12.43;
    cout << max(x,y) << endl;
}

Und nochmal für hinter den Spiegel stecken: Module bindet man via #include ein, indem man die Modul-Headerdatei einbindet! #include kann nur Headerdateien einbinden!!!

Vorkompilierte Header (in VC++ meistens die Datei "stdafx.h") müssen dem Compiler bekanntgemacht werden. In vorkompilierte Headerdateien sollte man nur solche Module einbinden und nur solche Prototypen ect. deklarieren, die man voraussichtlich danach so gut wie nicht mehr verändert! Es macht also Sinn, in der Headerdatei "stdafx.h" (man kann sie auch anders nennen, man muß das dem Compiler nur sagen) z.B. iostream.h einzubinden, da man diese Headerdatei (bzw. das iostream-Modul) nicht verändert. Der Compiler kompiliert dann das "stdafx"-Modul und linkt es später nur noch mit ein. Er wird es aber bei jedem neuen Kompilierungsdurchlauf nicht mehr mitkompilieren, da es ja bereits vorkompiliert wurde. Allerdings nur solange nicht, bis du etwas in "stdafx.h" bzw. "stdafx.cpp" änderst.

Beispiel an deinem Code:
Quellcode:// stdafx.h
#include <iostream.h>

Quellcode:// stdafx.cpp
#include "stdafx.h"

Quellcode:// maximum.h
double max(double, double);

Quellcode:// maximum.cpp
#include "maximum.h"

double max(double a, double b)
{
    return a>b?a:b;
}

Quellcode:// main.cpp
#include "stdafx.h"
#include "maximum.h"

void main()
{
    cout << max(2.3, 4.5) << endl;
}

Falls du dich jetzt fragst, wieso ich bei stdafx.h das Modul iostream eingebunden habe und nicht bei stdafx.cpp, dann sollte dies hier helfen:

Da jedes Modul unabhängig ist voneinander, würde ein #include <iostream.h> in stdafx.cpp bewirken, daß zwar das Modul stdafx alles aus <iostream.h> kennt, aber später main.cpp nicht (obwohl es ebenfalls stdafx einbindet)! Erst wenn #include <iostream.h> in stdafx.h steht (siehe oben), kennen es stdafx.cpp UND main.cpp! Schließlich binden beide Quelldateien stdafx.h ein und somit auch automatisch das darin enthaltene #include <iostream.h>. Praktisch sind Headerdateien große Interfaces (Schnittstellen), die für alle Quelldateien da sind. Und das main.cpp nach dem #include "maximum.h" auch die Funktion max() perfekt beherrscht liegt daran, daß beim Einbinden von maximum.h automatisch sowohl die Deklaration als auch die Definition der Funktion max() mit eingebunden wird.

Sowas zu beschreiben ist immer etwas schwierig, also rate ich dir DRINGENST ein gutes C/C++ Buch zu studieren!!! Insbesondere über die Techniken der Modularisierung!

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 03.05.2002 um 01:41 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
006
03.05.2002, 02:31
Tron



kriz: tipporgasmus? *G*

--

'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams

'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett

zum Seitenanfang zum Seitenende Profil || Suche
007
03.05.2002, 15:15
[RMen]OneStone



Nebenbei: Ich würd' Sachen wie min / max als inline deklarieren, d.h. sie werden vom Präprozessor direkt dahin geschrieben, wo sie aufgerufen werden (wie Makros).

--

georg-wicherski@pixel-house.net | http://www.pixel-house.net/ - Coding Resource| http://www.google.de/

zum Seitenanfang zum Seitenende Profil || Suche
008
03.05.2002, 17:12
Prefect



Zitat:
[RMen]OneStone postete
Nebenbei: Ich würd' Sachen wie min / max als inline deklarieren, d.h. sie werden vom Präprozessor direkt dahin geschrieben, wo sie aufgerufen werden (wie Makros).

Der Präprozessor hat mit inline-Funktionen nichts zu tun. inline-Funktionen funktionieren nicht wie Makros.

Da bleibt nur noch der erste Satzteil von deinem Posting übrig ;p

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
009
03.05.2002, 17:39
Kriz



Zitat:
[RMen]OneStone postete
Nebenbei: Ich würd' Sachen wie min / max als inline deklarieren, d.h. sie werden vom Präprozessor direkt dahin geschrieben, wo sie aufgerufen werden (wie Makros).

Ack, laberst du schon wieder Scheiße, Junge? >:/
Woher beziehst du eigentlich immer deine "genialen" (hust hust) Geistesblitze?

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
010
03.05.2002, 21:25
Leviathan



danke erstmal für den tipporgasmus kriz.
und was onestone gesagt hat ist prinzipiell richtig, später in der kompilierten datei sollten makros ähnlich wie inline-funktionen aussehen.
aber: makros sind eine textersetzung vor dem kompilieren, inlines sind eine codersetzung beim linken (soviel ich weiss)
allerdings ist es wirklich sinnvoll, soetwas wie mein beispiel als inline zu deklarieren.

zu meinen c++-kentnissen: ich kann c++ mittlmäßig, nur den präprozessor habe ich nie richtig begriffen, schon in c nicht. gibts da irgentein (deutsches oder englisches) tutorial zu, was leicht zu verstehen ist? in büchern wird der präprozessor immer nur kurz abgehandelt.

ich habe übrigens kriz´s vorschlag mal ausprobiert, das gibt bei mir pro funktion einen linkerfehler "nicht aufgelöstes externes symbol" (lnk2001) in msvc++
was mache ich falsch?muss ich beim kompilieren irgentetwas beachten (reihenfolge/einige dateien gesondert kompilieren)?

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche
011
03.05.2002, 23:45
Tron



Levi, das ist auch falsch, inline-funktionen wird direkt beim kompilieren eingefuegt, deswegen muss auch immer die implementierung der funktion direkt von der stelle des aufrufers einsehbar sein (will heissen in der datei drin oder per include)
inline wuerde beim linken nicht funktionieren, da hier der code schon fertig kompiliert ist und nur noch adresssymbole aufgeloest werden und alle .obj zu einer fertigen ausfuehrbaren datei gebunden (to link) werden.

onestone, laber net ueber sachen, die du nur halb verstanden hast.

--

'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams

'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett

zum Seitenanfang zum Seitenende Profil || Suche
012
04.05.2002, 13:02
Kriz



@Levi: Welchen Code hast du ausprobiert? Den normalen oder den mit der vorkompilierten Headerdatei?

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
013
04.05.2002, 14:21
[RMen]OneStone



Zitat:
d.h. sie werden vom Präprozessor direkt dahin geschrieben

Falsch, geb' ich ja zu.
Zitat:
(wie Makros)

Sollte nur ein anschaulicher Vergleich sein!

--

georg-wicherski@pixel-house.net | http://www.pixel-house.net/ - Coding Resource| http://www.google.de/

zum Seitenanfang zum Seitenende Profil || Suche
014
05.05.2002, 15:01
Leviathan



ich habe beides mal ausprobiert, mit und ohne vorkompilierten header.

aber: bei dem beispiel, dass ich hier gegeben habe funktioniert es, wenn ich die funktion allerdings als inline deklariere, bekomme ich den schönen linkerfehler (lnk2001).

die funktionen, für die ich deklaration und implementation trennen wollte sollen aber inline sein, da sie viele tausend mal aufgerufen werden, allerdings selber nicht rechenintensiv sind. mit makros lassen sie sich afaik nicht realisieren.

kann mir da einer eine möglichkeit nennen, wie ich das doch hinbekomme?

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche
015
05.05.2002, 21:45
Kriz



Hm... Inline Funktionen gehen nach folgendem Schema vor:

a) Der Compiler kann eine inline-deklarierte Funktion expandieren und Coderersetzung durchführen, muß aber nicht, da inline nur eine Empfehlung an den Compiler darstellt, keinen Zwang!

Beispiel:Quellcode:inline int quad(int x)
{
    return x*x;
}

Der passende Aufruf int a = quad(14); könnte in drei verschiedenen Fällen anders aussehen:

1. Fall: Keine Ersetzung, d.h. der Compiler verweist den Aufruf an die Funktion wie eine normal deklarierte Funktion.
2. Fall: Der Compiler ersetzt den R-Value durch die passende Expansion (int a = 14*14;).
3. Fall: Der Compiler ersetzt und konstantiert sofort beim Kompilieren den R-Value (int a = 196;).

2. und 3. Fall sind aber nur dann möglich, wenn man quad() einen konstanten Zahlenwert übergibt. Variablenübergabe bringt hier nichts, da Variablen erst zur Laufzeit (außer const Variablen) wertemäßig bekannt sind.

b) Inline Funktionen sind bei falscher Definition nur innerhalb ihres eigenen Moduls bekannt. Das ist immer dann der Fall, wenn man Funktionen in Quelldateien als inline definiert. Damit aber inline Funktionen auch in anderen Modulen als inline bekannt sind, muß man die Deklaration bereits in der Headerdatei vornehmen:

Beispiel, wie es nicht klappt:
Quellcode:// inlinetest.h
int quad(int);
int foo(int);

Quellcode:// inlinetest.cpp
#include "inlinetest.h"
inline int quad(int a) // inline
{
    return x*x;
}
int foo(int a) // normal
{
    a += 5;
    return quad(a); // inline von quad() ist hier bekannt
}

Quellcode:// main.cpp
#include "inlinetest.h"
void main(void)
{
    int x = 500,
        y;
    y = foo(x) + quad(x); // inline von quad() ist hier nicht mehr bekannt
}

Verlegt man nun die inline Deklaration in die Headerdatei, dann wird sie auch woanders als inline bekannt:
Quellcode:// inlinetest.h
inline int quad(int)
{
    return x*x;
}
int foo(int);

Quellcode:// inlinetest.cpp
#include "inlinetest.h"
int foo(int a)
{
    a += 5;
    return quad(a); // inline von quad() ist hier bekannt
}

Quellcode:// main.cpp
#include "inlinetest.h"
void main(void)
{
    int x = 500,
        y;
    y = foo(x) + quad(x); // inline von quad() ist hier jetzt auch bekannt
}

c) Inline Funktionen unterliegen dem internal linkage (internem Binden). Daher muß man globale inline Funktionalität immer in Headerdateien deklarieren.

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
016
06.05.2002, 17:23
Leviathan



danke nochmal kriz.
aber: bei dem 2. beispiel steht die implementation in der headerdatei, eine deklaration gibt es nicht. trotzdem eine gute lösung.

nachdem wir das hätten:

wie sieht das mit der schutzvorrichtung gegen mehrfach-#include aus?
ich habe was von #pragma once gehört, aber auch von #ifndef und #define?
was ist besser und wo liegen die unterschiede? (jaja ich beherrsche den präprozessor wirklich gut)

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche
017
06.05.2002, 17:51
Prefect



#pragma once ist eine MSC-Erweiterung.

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
018
06.05.2002, 23:30
Kriz



Damit redundantes Erzeugen von Dingen in Headerdateien ausbleibt, ganz einfach so handeln:
Quellcode:
// Headerdatei
#ifndef HEADERDATEI_H
#define HEADERDATEI_H
// Inhalt der Headerdatei
#endif // HEADERDATEI_H

Sobald ein Programmgerüst das erste Mal auf diese Headerdatei stößt, sieht der Präprozessor, daß HEADERDATEI_H noch nicht definiert wurde. Also definiert er HEADERDATEI_H und fährt hinter der Direktive fort. Der Inhalt der Datei steht sozusagen in einem Block drin. Den muß man dann am Ende der Datei mit einem beherzten #endif wieder schließen.

Sobald der Präprozessor später erneut auf diesen Code infolge mehrfacher #include Direktiven stößt, sieht er aber, daß vorher irgendwann einmal HEADERDATEI_H definiert worden ist. Er übergeht also alles bis zum #endif und das war's auch schon. So vermeidet man redundantes Datenmaterial.

Btw. ist das mehrfache Ausschließen innerhalb einer Datei durchaus drin! Man muß nur richtig die if-Blöcke schließen:
Quellcode:#ifndef A
#define A
// blub
#ifndef B
#define B
// möp
#endif // B
#endif // A

Daher schreibe ich mir hinter jedes #endif als Kommentar auf, zu welchem if-Block das ganze gehört =)

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
019
07.05.2002, 12:13
TheTinySteini



Jo, so mach ich das auch. Alles andere führt zum Code der Art "It was hard to code, it should be difficult to understand".

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy

zum Seitenanfang zum Seitenende Profil || Suche
020
07.05.2002, 18:56
Kriz



@TTT: Ich hoffe, du willst mir damit nicht sagen, daß ich dir gerade was Neues beigebracht habe ;) Das wäre ja skandalös bis in die Knochen! Hehehe...

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
021
07.05.2002, 19:21
TheTinySteini



Nein, das war nur eine Bestätigung, dass das sinnvoll ist und ich das auch so handhabe. Außerdem isses ja im HL-SDK auch so... und das kenne ich schon etwas länger =)

[edit]
... und in den Windoof-Headerdateien. Mehr #defines und #ifdefs kann's eigentlich gar nicht geben.

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy


Dieser Beitrag wurde am 07.05.2002 um 19:22 von TheTinySteini bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
022
07.05.2002, 19:55
Leviathan



dnake kriz, dem steini kanst du zwar nix mehr beibringen, dafür aber mir. ich habe mal in eine vom ms-compiler erzuegte klasse geschaut und da sieht es etwa so aus:

Quellcode:
#if ! defined HEADERDATEI_H_IRGENTWELCHE_ZEICHEN
//könnte auch #ifndef stehen
#define HEADERDATEI_H_IRGENTWELCHE_ZEICHEN
#if _MSC_VER > 1000
//compiler hat eine version, die once unterstützt?
#pragma once
#endif //_MSC_VER > 1000

//hier steht die klassendeklaration

#endif //HEADERDATEI_H_IRGENTWELCHE_ZEICHEN

das habe ich jetzt endlich begriffen und kann es selber auch in eigenen projekten umsetzen.
aber ich habe noch eine frage:
durch das #include mache ich dem kompiler nur den prototypen bekannt, aber woher kennt er die implementation? oder wird die erst im linker eingefügt?

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche
023
07.05.2002, 23:35
Kriz



Der Compiler befaßt sich eigentlich nur mit den Quelldateien. Die Headerdateien sind für ihn nur ganz einfach Klartextdateien, wo irgendwas drinsteht. Da der Compiler mittels Präprozessor erstmal alles in die Quelldateien einfügt, was dort eingefügt werden soll, sähe das ja im Endeffekt vor dem Präprozessieren so aus:
Quellcode:// a.h
int a(void);

Quellcode:// a.cpp
#include "a.h"

int a() { return 123; }

Quellcode:// b.h
int b(void);

Quellcode:// b.cpp
#include "b.h"

int b() { return 456; }

Quellcode:// main.cpp
#include <iostream.h>
#include "a.h"
#include "b.h"

void main()
{
    int erg = a()*b();
    cout << erg << endl;
}

So, nachdem der Präprozessor da durchgesaust ist, sieht das (im schlimmsten Fall) so aus:
Quellcode:// a.cpp
int a(void);
int a(void) { return 123; }

Quellcode:// b.cpp
int b(void);
int b() { return 456; }

Quellcode:// main.cpp
// Viel Code aus iostream.h
int a(void);
int b(void);

void main()
{
    int erg = a()*b();
    cout << erg << endl;
}

Deine Frage, warum in main.cpp trotz der dort nur vorhandenen Prototypen von a() und b() auch die Implementierungen aus a.cpp und b.cpp bekannt ist, liegt einfach daran, daß standardmäßig alle globalen Funktionen als extern deklariert sind und somit quelldateiübergreifend bekannt sind. Der Linker erkennt anhand seiner Cross-Reference-Tabelle, daß irgendwo a() und b() außerhalb von main.cpp implementiert worden sind. Er weiß dadurch, daß a() in a.cpp und b() in b.cpp implementiert worden sind und setzt dadurch einfach nur Querverweise (Jumps) beim Linken, die später im fertigen Programm aufgerufen werden.

Würden a() und b() bei der Deklaration explizit als static deklariert werden, dann wären sie nur in a.cpp bzw. b.cpp bekannt, aber nicht mehr in main.cpp. Es würde einen Linker-Error geben. Aus diesem Grund sind sie vom System aus immer standardmäßig (implizit) als extern deklariert, damit datt auch funzt!

Alles klar? =)

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 07.05.2002 um 23:36 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
024
08.05.2002, 19:00
Leviathan



nochmal danke kriz.
aber es ist noch immer nicht alles klar.
was genau heisst das static? ich weiss nur, was es für methoden eine klasse bedeutet, aber in globalen funktionen kann ich mir das nicht erklären.

und:

Zitat:

Würden a() und b() bei der Deklaration explizit als static deklariert werden, dann wären sie nur in a.cpp bzw. b.cpp bekannt, aber nicht mehr in main.cpp. Es würde einen Linker-Error geben. Aus diesem Grund sind sie vom System aus immer standardmäßig (implizit) als extern deklariert, damit datt auch funzt!

gilt das auch für explizites deklarieren als inline?

--

Entities: HL | HL²
Kompilierfehler
r_speeds | mehr über r_speeds

zum Seitenanfang zum Seitenende Profil || Suche