.
|
|
| 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: simples beispiel (gibt das maximum zweier doubles zurück):
ich hoffe mal ihr versteht die frage. --Entities: HL | HL² Dieser Beitrag wurde am 02.05.2002 um 20:06 von Leviathan bearbeitet. |
|
Profil || Suche |
|
001 02.05.2002, 21:11 Kriz |
K:R-I)Z++ |
|
Profil || Suche |
|
002 02.05.2002, 21:44 Leviathan |
danke schonmal dafür. Entities: HL | HL² |
|
Profil || Suche |
|
003 02.05.2002, 22:18 Kriz |
Einbinden kannst du nur Headerdateien: <headerdatei.h> // Datei liegt im Standard-Headerverzeichnis 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_1.h // Headerdatei 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++ |
|
Profil || Suche |
|
004 02.05.2002, 22:27 Leviathan |
danke nochmal, aber: nehmen wir mal folgendes hauptprogramm zu obigem beispiel:
Entities: HL | HL² |
|
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: Das erledigen wir nun mit der Hauptquelldatei, die wir mal main.cpp nennen: 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: 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++ Dieser Beitrag wurde am 03.05.2002 um 01:41 von Kriz bearbeitet. |
|
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 |
|
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/ |
|
Profil || Suche |
|
008 03.05.2002, 17:12 Prefect |
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, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
009 03.05.2002, 17:39 Kriz |
Ack, laberst du schon wieder Scheiße, Junge? >:/ Woher beziehst du eigentlich immer deine "genialen" (hust hust) Geistesblitze? -- K:R-I)Z++ |
|
Profil || Suche |
|
010 03.05.2002, 21:25 Leviathan |
danke erstmal für den tipporgasmus kriz. 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++ Entities: HL | HL² |
|
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) 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 |
|
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++ |
|
Profil || Suche |
|
013 04.05.2002, 14:21 [RMen]OneStone |
Falsch, geb' ich ja zu.
Sollte nur ein anschaulicher Vergleich sein! -- georg-wicherski@pixel-house.net | http://www.pixel-house.net/ - Coding Resource| http://www.google.de/ |
|
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² |
|
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: 1. Fall: Keine Ersetzung, d.h. der Compiler verweist den Aufruf an die Funktion wie eine normal deklarierte Funktion. 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: K:R-I)Z++ |
|
Profil || Suche |
|
016 06.05.2002, 17:23 Leviathan |
danke nochmal kriz. nachdem wir das hätten: wie sieht das mit der schutzvorrichtung gegen mehrfach-#include aus? Entities: HL | HL² |
|
Profil || Suche |
|
017 06.05.2002, 17:51 Prefect |
#pragma once ist eine MSC-Erweiterung. cu, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
018 06.05.2002, 23:30 Kriz |
Damit redundantes Erzeugen von Dingen in Headerdateien ausbleibt, ganz einfach so handeln: 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: K:R-I)Z++ |
|
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 |
|
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++ |
|
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] TheTinySteini Dieser Beitrag wurde am 07.05.2002 um 19:22 von TheTinySteini bearbeitet. |
|
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:
das habe ich jetzt endlich begriffen und kann es selber auch in eigenen projekten umsetzen. Entities: HL | HL² |
|
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: 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++ Dieser Beitrag wurde am 07.05.2002 um 23:36 von Kriz bearbeitet. |
|
Profil || Suche |
|
024 08.05.2002, 19:00 Leviathan |
nochmal danke kriz. und:
gilt das auch für explizites deklarieren als inline? -- Entities: HL | HL² |
|
Profil || Suche |
|

