Hilfe fürs Verstehen von C++ gesucht!

Marco7757

Mitglied
Hallo Freunde

Ich bin am Ende, völlig verzweifelt. Vor zwei Jahren habe ich einen Versuch gestartet, mit C++ klar zu kommen, ich bin auf der ganzen Linie gescheitert. Ich hatte keine Ahnung von OOP und bin mit dem ganzen System nicht klar gekommen. Eigentlich nicht weiter verwunderlich wenn man von PHP umsteigen will, welches inzwischen zwar auch OOP anbietet, meiner Meinung jedoch nicht wirklich nützlich ist, es ging jahrelang ja auch ohne ... (hier könnte man einen weiteren Thread starten, ich bitte euch jedoch eure meinung für euch zu behalten und mir bei meinem Problem zu helfen ;) )

Vor einigen Wochen dann der 2. Versuch. Ich beherrsche inzwischen Java und kann dort schon sehr nützliche Programme schreiben. Die objektorientierte Programmierung liegt mir inzwischen besser und ich kann sie verstehen, obwohl ich Sachen wie Interfaces und ähnliches nie nutze, die Vererbung nur selten.

Jedoch bin ich nun zum Schluss gekommen, dass es nicht am Programmiern liegt, denn das kann ich. Nein, mein Problem ist das ganze, riesige, unübersichtliche C++-System an sich, welches noch kein Buch und keine Internetseite für mih entwirren konnte.
Überall bekommt man die Grundlagen der Datentypen, der Variabeln, Konstanten, Schleifen, Klassen, Funktionen usw .. erklärt. Wer aber irgendwann einmal eine Programmiersprache erlernt hat, wird sich während 450 von 500 Seiten langweilen.

Meine Probleme sind allerdings anders. Und ich kann sie jetzt auch nicht alle niederschreiben da sie sich, wenn jemand meine Probleme beantworten kann, mit der Zeit lösen werden.
Ich beginne einfach mal mit der ersten Frage die mir einfällt:
Was ist der unterschied zwischen Header- und den Source-Files? Wieso schreibt man seinen Code (wie in Java) nicht einfach in einen Dateityp? Wieso steht in C++ eine Klasse mal in einer .cpp, mal in einer .h Datei?
Wieso werden Dialoge mit der Endung .rc gespeichert? Was hat das für einen Sinn? Ein Dialog wird (ich habe keine Ahnung) wie in Java doch auch einfach Code sein und in einer normalen Datei stehen ...

Ich beginne erst mal so. Ich hoffe ihr habt Antworten ...
 
Hier mal, was in einem Header steht: http://www.imb-jena.de/~gmueller/kurse/c_c++/c_heads.html

Zu .rc: Das ist mal wieder Visual C++, das lässt du am besten erstmal zur Seite.
Wieso steht in C++ eine Klasse mal in einer .cpp, mal in einer .h Datei?
Es geht beides.

Ein Dialog wird (ich habe keine Ahnung) wie in Java doch auch einfach Code sein und in einer normalen Datei stehen ...
Ein Dialog hat mit Standard-C++ erstmal nix zu tun, dass wird dann z. B. durch GUI-libs etc. nachgeliefert.


Da kommen nun sicher Unmengen von Rückfragen, vll. ist es besser, dass ganze direkt zu klären (ICQ etc.), bei Interesse, PM ;)
 
Zu cpp/h: Es gehört irgendwie zum "guten Ton", den Klassenaufbau und die Implementation zu trennen.
Dh, wenn man eine Klasse schreibt, schreibt man in eine h-Datei, welche Methoden/Variablen drin vorkommen, welche Parameter die Methoden bekommen etc.
Den Rumpf der Methoden (also den Code, der tatsächlichen ausgeführt wird) kommt dagegen in eine cpp-Datei.

Persönlich find ich das iwie übersichtlicher, als alles wie in Java in eine Datei zu wurschteln.

Theoretisch kannst du jedes noch so große Programm in eine einzige cpp-Datei quetschen (In Java muss ja jede Klasse eine eigene Datei haben, die Beschränkung gibts hier nicht); das würde auf Dauer aber ziemlich unübersichtlich werden.

Deshalb Aufteilen in mehrere cpp Dateien (jede mit einer h-Datei dazu); ist nicht zwingend, aber sinnvoll.

Das Gegenstück zum import in Java ist dann das #include mit der h-Datei, aber das kennst du ja wahrscheinlich schon.
 
Zur zweiten Frage: Grundsätzlich bietet das Betriebssystem von sich aus eine Reihe an Funktionen für Dialoge und generell alle grafischen Fenster an.
Gerade bei der Grafik sind diese aber meistens umständlicher als das, was du von Java kennst.

Statt einfach einen JButton zu einem JPanel adden und schon wird er angezeigt, gibts hier nicht.
Eher: "Zeichne bei den Koordinaten xy ein Rechteck, fülle es mit der Farbe z, schreib mit Schrift mno irgendwas hinein...". ist übertrieben, aber du verstehst, was ich meine.

Du kannst dir die komfortablen Java-Klassen wie JButton und alles drumherum als eine "Zwichenschicht" zwischen deinem Programm und dem Betriebsystem vorstellen, die, wenn du einen Button brauchst, als einzige Aufgabe dem Betriebssystem weitergibt, wo es jetzt ein Rechteck zu zeichnen hat etc.

Das Ganze ist bei Java von Haus aus dabei.

In C und C++ hingegen kannst du standardmäßig nur die Betriebsystemfunktionen verwenden.
Natürlich kannst du damit auch alles machen, was Java kann, aber in bestimmten Bereichen (vor allem bei den besprochenen Dialogen etc) ist es viel umständlicher als in Java.

Bevor du jetzt verzweifelst: Die "Zwischenschicht", wie ich sie genannt habe, gibts auch hier; nur nicht eine fixe, sondern eine größere Anzahl, aus der man sich aussuchen kann, welche man am liebsten hat:D

Theoretisch kann jeder, der ein bisschen Ahnung von der Materie hat, selber eine weitere schreiben und für die Öffentlichkeit irgendwo zum Download anbieten

Und bevor ich noch weiter von einer Zwischenschicht rede (grauenhaft), die sind besser bekannt als GUI-Librarys (hat badday ja schon erwähnt)

...
Also: Ja, ein Dialog ist prinzipiell auch nur normaler Code

Zu den rc-Dateien: Gehören praktisch zu einer von Microsoft entwickelten GUI-Lib (wenn man die so nennen kann), bei der man einen Dialog auch einfach zusammenklicken/malen kann.
Kennst du Jigloo? Ist damit vergleichbar.

Das angesprochene Microsoftteil bekommst du automatisch mit dem Microsoftcompiler mit, mit diversen anderen Sachen unter dem Namen "Visual Studio" verpackt

Im Lauf der Zeit haben verschiedene Leute ja auch mehrere Compiler gemacht...kann man sich auch aussuchen, welchen man am liebsten hat. Da gibts nicht nur den Standartcompiler von Sun.
Jeder, der Ahnung davon hat, kann sich selber einen machen :D
Ist aber eine andere Geschichte

Gruß

edit: irgendwie hab ich zuviel Zeit...
 
Vielen Dank! Das ist schon mal was!

Wenn ich das richtig verstehe, könnte man auch die eigentliche Klasse in die .h-Datei schreiben und das Interface (das ist doch das, wo man festlegt was die Klasse danach alles haben wird!?) in die .cpp-Datei?
Wieso sollte man, bei einer ganz normalen Klasse, überhaupt festlegen, was sie später einmal haben wird? Das lohnt sich doch irgendwie gar nicht, wenn man die Datei, in der die eigentliche Klasse steht, nicht auswechselt, diese also immer die gleiche bleibt und sich nie verändert ...?

Zu den Dialogen:
Ich habe Visual Studio und habe mir auch schon einige Dialoge zusammengebastelt. Allerdings finde ich, dass es 1000x länger geht wenn man jedes dieser Elemente mühsam reinzieht und dann die verschiedenen Attribute in einer endlos langen Liste festlegt. Ist es nicht auch, wie in Java, das per Code zu machen? Oder ist es, wie oben angedeutet, viel zu kompliziert?

Eine Frage zu den Bibliotheken: Verstehe ich das richtig, dass Bibliotheken einfach eine "Sammlung" von verschidenen/mehreren Klassen sind, die in eine Datei gepackt werden, damit man einfacher? schneller? auf sie zugreifen kann?
Was ist dann der Unterschied zwischen statischen und anderen Bibliotheken (.lib und .dll?) Was ist besser. Wie benutzt man eine solche Bibliothek? Einfach einbinden und dann die Methoden aufrufen?
 
Eine Frage zu den Bibliotheken: Verstehe ich das richtig, dass Bibliotheken einfach eine "Sammlung" von verschidenen/mehreren Klassen sind, die in eine Datei gepackt werden, damit man einfacher? schneller? auf sie zugreifen kann?
Was ist dann der Unterschied zwischen statischen und anderen Bibliotheken (.lib und .dll?) Was ist besser. Wie benutzt man eine solche Bibliothek? Einfach einbinden und dann die Methoden aufrufen?
Ja, eine Bibliothek ist eine Sammlung von Klassen, Funktionen und anderen Dingen.
Eine statische Bilbiothek (.lib) wird in die EXE gepackt, dadurch ist die EXE größer, aber man braucht keine extra Dateien mitliefern.
Eine dynamische Bilbiothek (.dll) wird zur Laufzeit geladen, dadurch ist die EXE kleiner, aber man muss diese DLL mitliefern.

Ich habe Visual Studio und habe mir auch schon einige Dialoge zusammengebastelt. Allerdings finde ich, dass es 1000x länger geht wenn man jedes dieser Elemente mühsam reinzieht und dann die verschiedenen Attribute in einer endlos langen Liste festlegt. Ist es nicht auch, wie in Java, das per Code zu machen? Oder ist es, wie oben angedeutet, viel zu kompliziert?
Wie gesagt, C/C++ hat keine GUI von "Haus aus". Wenn man eine GUI will, muss man die Plattform API des entsprechenden Systems nehmen, z.B. Windows API. GUI-Frameworks (oder -Bilbiotheken) bieten dafür Klassen an, mit denen sich es leichter programmieren lässt.

Wenn ich das richtig verstehe, könnte man auch die eigentliche Klasse in die .h-Datei schreiben und das Interface (das ist doch das, wo man festlegt was die Klasse danach alles haben wird!?) in die .cpp-Datei?
Wieso sollte man, bei einer ganz normalen Klasse, überhaupt festlegen, was sie später einmal haben wird? Das lohnt sich doch irgendwie gar nicht, wenn man die Datei, in der die eigentliche Klasse steht, nicht auswechselt, diese also immer die gleiche bleibt und sich nie verändert ...?
Interface?
Alle Variablen und Typen, darunter auch Klassen, haben eine Deklaration und eine Definition.
Eine Deklaration ist die Festlegung, dass es die entsprechende Variable/Typ gibt.
Eine Definition ist das Definieren des Wertes der Variablen oder der Eigenschaften und Methoden bei Klasse.
Meistens packt man die Deklaration für Klassen in eine sogenannte Header-Datei (.h) und die Definition in eine sogenannte Source-Datei (.cpp)
 
Wenn ich das richtig verstehe, könnte man auch die eigentliche Klasse in die .h-Datei schreiben und das Interface (das ist doch das, wo man festlegt was die Klasse danach alles haben wird!?) in die .cpp-Datei?

Dann wäre alles umgedreht...wozu zweckentfremden? Welcher Teil in h und welcher zu cpp gehört, ist nun mal
so festgelegt.

Wieso sollte man, bei einer ganz normalen Klasse, überhaupt festlegen, was sie später einmal haben wird? Das lohnt sich doch irgendwie gar nicht, wenn man die Datei, in der die eigentliche Klasse steht, nicht auswechselt, diese also immer die gleiche bleibt und sich nie verändert ...?

Es gibt noch einen weiteren Grund außer der Übersichtlichkeit.
zB:

klasse.h:
C++:
class klasse
{
    protected:
        int erg;
    public:
        void plus(int,int);
        int ergebnis();
};

klasse.cpp:
C++:
void klasse::plus(int a,int b)
{
    erg=a+b;
}

int klasse::ergebnis()
{
    return erg;
}

Und dazu zwei Quellcodedateien, die Teil vom gleichen Programm sind, und beide haben ein
#include<klasse.h>
am Anfang stehen.

So wäre alles in Ordnung.
Das Include ist deshalb nötig, weil: Jede cpp-Datei einzeln kompiliert wird und die Ergebnisse erst dann zu einem Programm zusammengefügt werden (durch den Linker)
Wenn jetzt in einer der zwei Datei zB plus verwendet wird, muss der Compiler prüfen, ob es auch in Ordnung ist, dass zwei int übergeben werden; und sich aufregen, wenns nicht so ist.

Angenommen die eine von den verwendeten Dateien hat die Funktionen x1 und y1, die andere x2 und y2.
x1 und x2 rufen plus der Klasse auf, y1 und y2 rufen ergebnis auf.

Nach dem kompilieren wissen die Dateien:
Datei 1: Ich habe x1 und y1 und brauche klasse:: plus und klasse::ergebnis, die hab ich aber nicht
Datei 2: Ich habe x2 und y2 und brauche klasse:: plus und klasse::ergebnis, die hab ich aber nicht
klasse.cpp: Ich habe klasse:: plus und klasse::ergebnis

Die werden dann zusammengelinkt und fertig.

Wenn aber die klasse.cpp fehlen würde und die h-Datei so ausschauen würde:
C++:
class klasse
{
    protected:
        int erg;
    public:
        void plus(int a,int b){erg=a+b;}
        int ergebnis(){return erg;}
};
Würde die Situation so sein:

Datei 1: Ich habe x1, y1, klasse:: plus und klasse::ergebnis
Datei 2: Ich habe x2, y2, klasse:: plus und klasse::ergebnis
klasse.cpp: Ich habe klasse:: plus und klasse::ergebnis

Jetzt ist beim Zusammenfügen das Problem, dass der Linker nicht mehr weiß, welche von den drei plus und ergebnis nun die richtigen sind.

Lange Rede, kurzer Sinn: Headerdateien verwindern Namenskonflikte
 
Zuletzt bearbeitet:
Zu den Dialogen:
Ich habe Visual Studio und habe mir auch schon einige Dialoge zusammengebastelt. Allerdings finde ich, dass es 1000x länger geht wenn man jedes dieser Elemente mühsam reinzieht und dann die verschiedenen Attribute in einer endlos langen Liste festlegt. Ist es nicht auch, wie in Java, das per Code zu machen? Oder ist es, wie oben angedeutet, viel zu kompliziert?

Von der Dauer her sind wir der gleichen Meinung:)
Wie gesagt, grundsätzlich wird keine Bibliothek von Anfang an mitgeliefert.
Mit Visual Studio dazu bekommt man aber auch eine von Microsoft, eben mit der Zusammenklickerei und den rc-Dateien.

(Damit kein Irrtum entsteht: Normalerweise bekommt man mit einer Bibliothek keine Zusatzfunktionen im Visual Studio selber, nur für den Code.
Aber da beides vom gleichen Hersteller ist, arbeitet das aussergewöhnlich gut zusammen :D)

Möglichkeiten sind also:
a) Du verwendest weiter die Zusammenklickerei
b) Du verwendest die puren Betriebssystemfunktionen (wie gesagt nicht sehr effektiv)
c) Du besorgst dir eben eine weitere GUI-Library:)

Die musst du allerdings eben erst auf deinen Rechner bekommen, bevor du sie verwenden kannst (Internet etc)
Besteht im Grunde auch nur aus lib/dll-Dateien
Bekannte Vertreter für den Bereich sind Qt und wxwidgets
Download, Tutorials und Dokumentation findet man leicht über Google

Ach ja, du verstehst es richtig: Eine Bibliothek/Library ist eine Sammlung von zusammengehörenden Funktionen, Klassen etc etc.

Warum sie gebündelt werden? Naja, weil sie zusammengehören:)
Bibliotheken können in sich wieder aus hunderten Dateien bestehen; du hätte keiner eine Freunde wenn er zu seiner einzigen cpp-Datei Hundert weitere mitkompilieren müsste, Hundert includes reinschreiben...

Statische(lib)/Dynamische(dll) Bibliotheken: Dazu gehört immer (min. eine) h-Datei, lib-Datei (auch bei dynamischen) und nur bei dynamischen auch eine dll.

Ich hab doch geschrieben, das jede cpp-Datei einzeln kompiliert wird und dann alle zusammen zu einer Exe zusammengefügt werden.
Eine statische Bibliothek kannst du dir wie ein weiteres h/cpp-Paar vorstellen, das auch dazugehört.
Einziger Unterschied: Die cpp ist schon kompiliert und muss dann (wenn die anderen auch kompiliert sind) nur noch zusammen mit in die Exe reingestopft werden.
Die vorkompilierte cpp-Datei ist eben die lib.

Bei der dynamischen ist nur ein Unterschied: Der vorkompilierte Teil bleibt eine eigene Datei. Eben die dll.
Vorteil: Wenn mehrere Programme die gleiche Bibliothek brauchen, kommen sie mit einer DLL aus. Das spart Speicher.
Noch ein Vorteil: Wenn sich was in der Bibliothek ändern soll, muss nicht das gesamte Programm neu kompiliert und ersetzt werden, sondern nur die DLL.
Nachteil: Ohne DLL funktioniert das Programm nicht. Muss also auf jeden Rechner mit, der das Programm verwenden will.

Wie man solche Bibliotheken benutzt:
Die dazugehörende h-Datei wie gewohnt mit include einbinden.
Zum kompilieren wird auch die lib benötigt (dynamisch oder nicht ist egal).
Wo man die angibt, unterscheidet sich aber bei den Entwicklungsumgebungen/Compilern.

Bei Visual Studio ist es wo im Menü Projekt-Einstellungen.
Da sollten auch schon ein paar andere libs stehen, die von Haus aus beim Betriebssystem dabei sind (eben damit man die Funktionen vom Betriebssystem verwenden kann, und nicht nur im Grafikbereich)
Sollte also kein Problem sein, die zu finden. Dort einfach deine dazuschreiben

Gruß
 
Zuletzt bearbeitet:
Statische(lib)/Dynamische(dll) Bibliotheken: Dazu gehört immer (min. eine) h-Datei, lib-Datei (auch bei dynamischen) und nur bei dynamischen auch eine dll.
Jein. Man kann dynamische Bibliotheken auch ohne eine .lib verwenden, indem man sie zur Laufzeit über die API des Betriebssystems lädt. Das ist z.B. bei Plugin-Mechanismen notwendig, wenn beim Kompilieren nicht bekannt ist, welche Plugins in Zukunft mit dem Programm verwendet werden.

@Marco7757: sheel und ComFreek haben dir ja schon recht ausführlich erklärt, wie aus einem C/C++-Projekt ein ausführbares Programm wird. Ich möchte das ganze Vorgehen trotzdem nochmal etwas schematischer erläutern, vielleicht wird es so noch klarer. Der Prozess lässt sich grob in drei Phasen unterteilen:

  1. Präprozessorphase
    Der Präprozessor wertet sämtliche Direktiven wie #include oder #define in der Eingabedatei aus und führt simple Textersetzungen durch. Ein „#include "header.h"“ wird beispielsweise durch den Inhalt der Datei header.h ersetzt.
  2. Übersetzungsphase
    Die Ausgabe des Präprozessors wird an den Übersetzer weitergereicht. Man nennt die Eingabe des Übersetzers auch eine Übersetzungseinheit. Sie besteht in der Regel aus einer einzelnen .cpp-Datei, in die über den Präprozessor ggf. andere (Header-)Dateien eingebunden wurden. Der Übersetzer generiert nun aus den Definitionen in der Übersetzungseinheit Maschinencode und gibt eine Objektdatei aus (unter Windows sind das die .lib-Dateien). Eine Objektdatei enthält ein Inhaltsverzeichnis über die darin befindlichen Funktionen, globalen Variablen etc. und den zugehörigen Maschinencode. Jede Übersetzungseinheit erzeugt genau eine Objektdatei.
  3. Linkphase
    In der letzten Phase werden die einzelnen Objektdateien zu einer einzigen Datei kombiniert (gelinkt). Dabei werden u.a. externe Verweise aufgelöst und die Funktion mit dem Namen main als Einsprungspunkt der Anwendung gesetzt. Schlussendlich kommt in diesem Schritt die endgültige ausführbare Datei heraus.

Zur Auflösung externer Verweise in der Linkphase: bspw. kann in Objektdatei A eine Funktion f aufgerufen werden, die in Objektdatei B definiert ist. Der Übersetzer würde dann an die Stelle des Aufrufs den Vermerk setzen, dass die Funktion f in einer anderen Objektdatei (die ihm aber nicht näher bekannt ist) definiert sein muss. Der Linker sieht diese Vermerk und ersetzt ihn durch einen Verweis auf die Adresse von f in Objektdatei B. Wenn es in diesem Schritt allerdings mehrere Funktionen namens f in unterschiedlichen Objektdateien gibt, dann gibt der Linker einen Fehler aus. Er weiß nämlich nicht, welche der Funktionen gemeint ist. Das würde z.B. passieren, wenn in der Headerdatei f.h die Funktion f definiert (und nicht nur deklariert) ist und sie von mehreren Übersetzungseinheiten (.cpp-Dateien) eingebunden wird. Dann landet die Funktion f in allen aus diesen Übersetzungseinheiten entstehenden Objektdateien.

Deshalb gilt die allgemeine Faustregel: in mehreren Übersetzungseinheiten verwendete Deklarationen gehören in eine gemeinsam genutzte .h-Datei, deren Definitionen in eine .cpp-Datei.

Ich hoffe ich konnte damit mehr Verwirrung auf- als auslösen.

Grüße,
Matthias
 
Zurück