Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Anonymous

unregistriert

1

20.08.2004, 02:37

OOP und C++ vs. C

Hi, ich möchte in meinen Projekten rein OO programmieren.

Meine Frage ist eigentlich einfach:

1.
Wenn ich z.B. Strukturen benutze und Klassen, muss ich dann zwangsläufig die Strukturen in den Klassen kapseln oder kann ich auch, ohne das OOP Paradigma zu brechen, die Strukturen ausserhalb einer Klasse definieren?
Das gleich gilt für Enums und Typedefs.

Ich benutze Namespaces, damit die zusammengehörigen Klassen besser zu erkennen sind. Könnte ich jetzt quasi Strukturen usw. innerhalb eines Namespaces definieren und damit dem OOP Paradigma gerecht werden.

2.
Ich würde eigentlich auch gerne auf C-Code verzichten und rein C++ programmieren, leider wurde mir in meinen Anfängen C-Code/ C++ Code gemischt beigebracht und ich habe heute echt Probleme zu sagen, dass ist kein C. Wie sieht es da z.B. mit Typedefs aus ... die gehören doch auch noch zu C++ oder.

Meine Fragen sind eigentlich eher trivial, aber ich hoffe trotzdem das mir wieder jemand weiterhelfen kann. Da man solche Fragen in keinem Buch findet, zumindest wüsste ich nicht nach was ich dort suchen sollt. Abgesehen von der Typdef Frage.

2

20.08.2004, 10:30

1) Weiß ich selbst nich so genau :D
2) Wenn du rein C++ programmieren willst, kauf dir nen C++ Buch wie zum Beispiel 'Die C++ Programmiersprache'. Dort wird dann wirklich nur C++ behandelt(grad bei dem werden aber, so weit ich weiß, immer noch die Unterschiede zwischen C und C++ behandelt(immerhin etwas C :D); ansonsten aber nicht)

Anonymous

unregistriert

3

20.08.2004, 11:22

Danke, also 1. steht noch aus und zu zweitens:
Das Buch hab ich bereits. Aber meist ist eine Frage im Forum ergibiger und schneller, als in einem Buch mit über 1000 Seiten zu suchen. Aber OK, im Prinzip hast du Recht, da würde ich sicher eine Antwort auf Frage 2. finden.
Das Problem ist, ich bin gerade unterwegs (Game Convention) und hab leider das Buch nicht mit ;-)

Ich habe aber noch eine dritte Frage:
3.
Ich arbeite z.B. an einer kleinen Engine, die ich in mehrere Subengines aufteile. Zum Beispiel die GraphicsSubEngine.
Die Engine wird durch ein Plugin System gesteuert, d.h. ich habe ein Basis Plugin z.B. Kernel, das ich immer in die Spiele einbinde und alle SubEngines werden dann bei bedarf geladen.
Basisfunktionalität wie ein LogSystem oder ein ExceptionSystem werden im Kernel erzeugt und verarbeitet. Erzeuge ich jetzt durch den Kernel auf Wunsch z.B. die SubEngine Graphics, dann möchte ich das diese auch auf mein LogSystem zugreifen kann.
Meine Idee:
Ich übergebe bei erzeugen der Serverklasse, die praktisch den Einstiegspunkt in die SubEngine darstellt einen Zeiger auf mein Kernel Objekt mit. Damit würde ich sicherstellen, dass meine SubEngine auch auf die Log Funktionalität zugreifen kann.
Aber
1. Zerstört das nicht die dynamische Denkweise eines Pluginsystem, wenn ich die SubEngines an den Kernel binde?
2. Wie kann ich diesen Zeiger für alle Komponenten in der SubEngine sharen, ohne an jeden Konstruktor den Zeiger weiterreichen zu müssen. Ich gehe davon aus, dass das eher eine schlechte Lösung wäre.

Ich dachte mir vielleicht, wenn ich ja alles in einer Namensraum kapseln werden, dann könnte ich es in einer "globalen konstanten" Variable im Namensraum sharen. Aber würde das eine gute Lösung sein und vorallem OO? Weil ich eigentlich nicht mit globalen Variablen arbeite.

Ok, ich hoffe man kann mein Problem verstehen und vielleicht hat ja jemand eine gute Idee :angel:

Anonymous

unregistriert

4

20.08.2004, 11:39

Mir ist gerade schon ein Lösungsansatz für 3. eingefallen. Vielleicht ist es nur ein Work-Around, aber schon einmal ein Anfang. Deshalb bin ich weiterhin an anderen Ideen interessiert.

Idee zu 3 :: Problem des sharen des Kernel Zeigers
In meiner Serverklasse, z.B. dem GraphicsServer share ich den Zeiger durch einen Zugriff auf eine private Member Variable durch einen entsprechende get/set- Methode.
Vorteil:
Ich wahre die Hierarchie in dem ich es nur der Serverklasse erlaube den Zeiger auf den "weiter oben" angeordneten Kernel zuzugreifen und allen "tieferen" Klassen im Subsystem, z.B. dem ResourcenManager erlaube ich es wieder nur eine Stufe nach oben zugehen, nämlich zum Server, um von diesem den Zugriff auf den Kernel zu erlangen.
Dadurch habe ich nicht das Problem, dass ich bei späteren Änderungen mehrere Klassen in einem Subsystem ändern muss. Und ich habe eine einfache Zugriffshierarchie.

Wie gesagt, ist nur mein erster Einfall. Wenn er nicht sonderlich gut ist, bitte schnell mit Begründung melden ;-) und mir gern bessere Ideen schreiben.

Manchmal sieht man den Wald vor lauter Bäumen nicht :(

5

20.08.2004, 13:59

Zu 1: Man kann Strukturen auch gut in den Namensraum stecken. Man muss nicht immer alles in eine Klasse packen. Eine Struktur ist ja eine Möglichkeit einen eigenen Datentyp zu Definieren. Ist aber keine Strenge sicht ;)
Für Enumerationen ist das nicht anders.

Zu 3: Dein Ansatz ist gar nicht so schlecht. Aber ich frage mich ob es denn unbedingt so kompliziert sein muss? Sicher in deinem Ansatz kann jedes Sub-Root-Objekt (z.B. der GraphicServer) den EngineServer noch einmal kapseln und einige Methoden überschreiben. Aber es stellt sich mir die Frage ob das unbedingt nötig ist.
Ich habe in etwa das selbe System wie du. Ich habe einen Engine Manager, der den einstieg in die Engine darstellt. Dieser beinhaltet das File-System, PlugIn-System, Log-System und die Fehlerbehandlung, sowie natürlich die Interfaceverwaltung.
Mehr soll der Manager nicht können, daher war es für mich nicht notwendig, eine solche Hirachie aufzubauen. Jedes Objekt bekommt daher einen Zeiger auf die Instanz des Manager Objektes. Unterobjekte wie z.B. ein Mesh-Interface bekommen zusätzlich noch den Zeiger des Graphic-Intefaces.

Dein System bietet natürlich ein bischen mehr flexiblität. Das bedeutet aber auch das jedes Sub-System die Fähigkeiten deines Managers bekommen.


Noch ein ansatz:
Ich empfehle auf jeden Fall ein Interface Design. Das bringt ein höchstmaß an flexiblität mit sich und hat den Vorteil das man die DLL's nicht fest mit einander verlinken muss.
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Anonymous

unregistriert

6

20.08.2004, 20:41

Danke DragonMaster für deine Antwort.

Interfaces sind auf jeden Fall geplant. Ich war nur noch nicht sicher ob es Sinn macht für praktisch jede Klasse ein Interface zu definieren, um dadurch auch spätere Ideen abzufangen. Oder wirklich nur Interfaces für Klassen, wo ich sicher bin, dass ich mehrere Implementierungen haben kann, z.B. das RenderSystem.

Eine Frage zu deinem Ansatz. Wenn du auch das LogSystem im Manager einbettest, wie haben dann andere Klassen Zugriff auf das Logsystem, ohne einen Zeiger auf die Managerklasse oder davon geerbt zu haben?

Das ist im Prinzip mein eigentliches Problem. Ich möchte die Bindung so gering wie möglich machen, aber ich brauch z.B. das LogSystem in den meisten Klassen. Am Besten wäre es eben, wenn jede SubEngine unabhängig von den anderen ist, um sie später einfach austauschen zu können.

Wie genau funktioniert das bei dir mit dem Zugriff von einem Plugin heraus auf den Manager?

7

20.08.2004, 21:40

@LogSystem:
Mein LogSystem besteht aus dem Engine Manager (der wie ein Textur-Manager arbeitet) und einem Log-Interface. Das dann die eigentlichen einträge in die Log-Datei macht. Wie auch immer diese aussehen. Dadurch ist es sowohl dem Manager als auch dem jeweiligen Interface egal, wie und wo sie ihre Log-Einträge machen. Das bestimmt allein der User und die Log-Klasse.

Und so ist eigentlich alles bei mir aufgebaut. Einfach alles wird hinter einem Interface versteckt. Selbst der Engine Manager ist hinter einem Interface versteckt. Das ist bei mir auch deswegen, weil ich für jedes Interface bestimmen kann ob es eine Debug- oder eine Release-Version sein soll.

Zitat

Wie genau funktioniert das bei dir mit dem Zugriff von einem Plugin heraus auf den Manager?
Über einen Zeiger der vom Typ class r3d::IManager ist (also ein Interface). Der Zeiger wird über den Konstruktor der Implementierungen übergeben.
Ich habe hier eine stricke Hirarchie aufgebaut. Vom einfachen Engine Object (Der Manager sieht nur dieses Interface) bis zur Implementierung eines Interfaces. Für jeden Schritt gibt es eine Unterkategorie.

z.B. Mein Mesh Interface (r3d::gfx::IMash) ist von insgesamt 5 Basisklassen abgeleitet. Auf diese weise erhalte ich für jede Stufe ein passendes Interface. Beim Material-Interface siehts noch schlimmer aus :)

Wenn du willst kann ich dir ja mal meine Klassen-Hirarchie schicken. Kannst mir deine eMail ja in einer pm schicken.
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

helium

Treue Seele

Beiträge: 180

Wohnort: NRW, Burscheid (nahe Köln)

  • Private Nachricht senden

8

15.09.2004, 09:57

Zitat


Wenn ich z.B. Strukturen benutze und Klassen, muss ich dann zwangsläufig die Strukturen in den Klassen kapseln oder kann ich auch, ohne das OOP Paradigma zu brechen, die Strukturen ausserhalb einer Klasse definieren?
Das gleich gilt für Enums und Typedefs.


Was sind für dich Strukturen?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Foo {
   void methode ()
   {...}
private:
   int x;
};

struct Bar : Foo {
   void whatever ()
   {...}
private:
   int y;
};


Sind das Strukturen, nur, weil struct davor steht?
Du musst schon konkreter sagen, was du mit Struktur meinst.

Instanzen von Aufzählungen (Enumerations => Enums) kannst du doch toll als Objekte ansehen.

C-/C++-Quelltext

1
2
3
enum Himmelsrichtung {Nord, Ost, Sued, West};

Himmelsrichtung himmelsrichtung = Nord;


Das ist perfekt OO. Dennoch kann es oft sinnvoll seine sie zu Kapseln. Das ist Situationsabhängig, genauso, wie es sinnvoll sein kann Klassen in anderen Klassen wegzukapseln, was aber eher selten vorkommt.

typedefs sind wichtig für die Template-Meta-Programmierung. Ansonsten sind sie nur eine Schreibvereinfachung und vollkommen Paradigmenunabhängig.

Zitat


Ich benutze Namespaces, damit die zusammengehörigen Klassen besser zu erkennen sind. Könnte ich jetzt quasi Strukturen usw. innerhalb eines Namespaces definieren und damit dem OOP Paradigma gerecht werden.

Nein. Namensräume haben absolut nichts mit Objektorientierung zu tun. Deswegen kannst du durch ihre Verwendung dein Programm auch nicht "objektorientierter" machen.
Und glaub bitte auch nicht, das du, nur wil in deinem Programm Klassen verwendest, objektorientiert Propgrammierst. Denk immer daran, das es Objektorientierung heißt, nicht Klassenorientierung. Mit Klassen hat das ganze wenig zu tun. neben der klassenbasierten Objektorientierung gibt es nämlich auch die prototypbasierte Objektorientierung (siehe z.B. SELF). Da kann man objektorientiert Programmieren, ohne dass es ein Konstrukt vergleichbar mit Klasse in C++ gäbe.

helium

Treue Seele

Beiträge: 180

Wohnort: NRW, Burscheid (nahe Köln)

  • Private Nachricht senden

9

15.09.2004, 10:03

Zitat


Ich würde eigentlich auch gerne auf C-Code verzichten und rein C++ programmieren, leider wurde mir in meinen Anfängen C-Code/ C++ Code gemischt beigebracht und ich habe heute echt Probleme zu sagen, dass ist kein C. Wie sieht es da z.B. mit Typedefs aus ... die gehören doch auch noch zu C++ oder.

Alle Sprachbestandteile von C++ gehören auch zu C++, egal, ob sie von C übernommen wurden, aus Simula67 stammen oder Eigenkreationen sind.
Auch das verwenden von aus C-Stammenden Bibliotheken macht deinen Code nicht weniger C++. In C++ gibt es absichtlich keine Alternative zu <math.h>, sondern lediglich eine nennen wir es Umwandlung in <cmath>. Der einzige Unterschied ist, dass sich die Bibliothek im Namensraum std befindet. Dennoch ist dieser Teil genauso Prozedural, wie eh und je.

C++ ist keine reine OO-Sprache. Sie war auch nie als solche gedacht. Du wirst immer prozedurale bestandteile Entdecken.

Aber darum ging es ja eigentlich gar nicht. Es ging darum in C++ nicht C zu programmieren, was IMHO eine vernüpfige Idee ist. Dabei geht es aber mehr darum die typischen Vorgehensweise abzulegen.

Werbeanzeige