Wie included ihr?

Macan

Mitglied
Grüss euch,

also mit der Struktur der .h/.cpp Dateien komme ich immer noch nicht so ganz klar (mag auch an der "event driven" Schreibe liegen).

Darum habe ich eine grundsätzliche Frage zu den Include Dateien. Natürlich hätte das auch im C++ Forum Platz, aber es gibt ja doch den einen oder anderen Unterschied zu .net (gerade die managed classes sind ja etwas restriktiver als normale C++ Klassen - z.B. erlauben sie kein "extern ref class bla^ blub;).

Angenommen, man hat folgende Klassen bzw. Include Dateien:
Code:
Datei C
|
Datei B
|
Datei A
Hier ist ja alles in Ordnung.

Code:
Datei C       Datei D       Datei E
|             |             |
--------------|             |
              Datei B       |
              |             |
              --------------|
                            Datei A
Hier gibt es auch kein Problem

Aber was macht man z.B. hier?

Code:
                ------- Datei C -------
Datei D -------|                       |------- Datei A
                ------- Datei B -------
Also Datei D wird von Datei B und C benötigt und Datei A benötigt Datei B, C (direkt) und auch Datei D. Ist dann für einen Objektorientierten Programmierer die Struktur des Programms einfach falsch oder wird dann eben so, wie im ersten Beispiel, eingebunden? Wenn Datei B und C jeweils Datei D includen würden, dann gäbe es ja schon Probleme.
Und was wäre dann, wenn Datei B auch noch Datei C (und vielleicht sogar noch umgekehrt) benötigt? Wie gesagt, wir sprechen hier immer von ref class und keinen normalen Klassen (also "extern" geht wohl nicht).

Gibt es da dann Möglichkeiten, sich zu helfen?
Oder, anders gefragt, wie wird ein #include Pfad gebastelt, der eben diese Abhängigkeiten auch befriedigen kann?

EDIT:
Ich sollte vielleicht noch dazu sagen, warum ich hierfür eine Lösung suche:
In meiner Applikation habe ich eine Ereignis-Klasse erstellt, die wirklich von jedem Programmteil (also in jedem Header) aus erreichbar und ausführbar sein soll. In diesem Falle habe ich hier die wichtigsten Methoden und Variablen sowieso schon static bzw. static delegates auf die Event-Methode (also den Auslöser des Events). Und da ich eben keine einfache Include-Hierarchie realisieren kann, stehe ich eben vor dem beschriebenen Problem.

Ich hoffe, meine Fragen erscheinen nicht zu dämlich :)
 
Zuletzt bearbeitet:
Hey Marcan :D

hmm... ich versteh nicht genau, was dein Problem ist...

aber ich versuch einmal dir eine Erklärung bezüglich dem Inkludieren von Datein zu geben, so gut ich kann XD

also, um einzelne Datein einzubinden, die sich im selben Project befinden benutzt du
#include + Pfad und Name

Wird üblicherweise in cpp files verwendet, um die dazugehörigen header einzubinden
also z.B.:
C++:
#include "tao/Object_T.h"
Um Datein aus dem Framework zu includieren, benutzt die Angle-bracket form mit < >
C++:
#include <stdio.h>

Um ganze Klassen, die woanders definiert sind, verwenden zu können benutzt du am Besten namespaces, in denen Klassen, Klassenmembers und Methoden definiert werden können...

C++:
// namespace RailControls
namespace RailControls
{
	// Klasse GridLocation in namespace RailControls
	public value class GridLocation
	{
	public:
		int X,Y;

		GridLocation(int i_x,int i_y)
			:X(i_x),Y(i_y)
		{
		}
	};

	// Klasse GridControl in namespace RailControls
	public ref class GridControl abstract
	{
		//  GridControl Klasseneigenchaften und Methoden
	};

	public ref class Rail abstract : public GridControl
	{
	public:
		Rail()
		{
		}

		enum class Direction
		{
			LEFT, RIGHT
		};
		
		ref class Connection
		{
		},
}

Um nun diese Klassen an anderen Stellen verwenden zu können, benutzt du
using namespace RailControls;

nun kannst du einfach Elemente der Klasse RailControls erstellen, indem du den namespace voranstellst:
C++:
// z.B:
Generic::List<RailControls::Rail::Connection ^> ^ Connections,
//  List <Typ> name;   ==> Typ = namespace RailControls, Klasse Rail, Klasse Connection

Hoffe, das hat die ein bisschen weitergeholfen *gg*

weitere Informationen zur verwendung von include und namespaces findest du mit Sicherheit in der MSDN
http://msdn2.microsoft.com/de-de/default.aspx

Ansonsten, wenn du vorhast von C auf managed VC++.NET umzusteigen,
kann ich dir einige Bücher empfehlen:
Julian Templeman, Andy Olsen - MS VC++.NET Schritt für Schritt
http://www.amazon.de/SV-Visual-C++-...sr_1_3/302-9104368-9925643?ie=UTF8&s=software

Kommen erst, kann man aber bereits vorbestellen:
http://www.amazon.de/Microsoft-Visu...4/302-9104368-9925643?ie=UTF8&s=books-intl-de
http://www.amazon.de/Managed-NET-De...3/302-9104368-9925643?ie=UTF8&s=books-intl-de

na dann...
k33p it GangZta,
all your base are belong to us XD
 
Zuletzt bearbeitet:
Eine Klasse kann nicht von 2 Klassen gleichzeitig ableiten, also versteh ich nicht wie Datei A von Datei B und Datei C gleichzeitig abhängig sein soll?
Es geht nur entweder oder.
Bei interfaces wäre das natürlich was anderes, weil von Interfaces kann man bekanntlich ja mehrere verwenden.

//edit: Ich bin übrigens C# Programmierer, keine Ahnung wie das bei C++ so ist ;)
Bei C# würde man das mit Interfaces lösen.

//edit2: Habe mich gerade mit leitman unterhalten. Wenn Du meinst, dass Du nicht ableitest sondern einfach auf die Klassen zugreifst, ist das Problem ebenfalls nicht ersichtlich für mich.
Wenn du ein Objekt (A) (Anmk.: FU leiti :D) erzeugst von der Klasse C, kann es sich der Methoden aus Klasse B nicht bedienen. Aber sehrwohl denen von Klasse D, wenn B und C davon ableiten.
 
Zuletzt bearbeitet:
Grüss euch zwei :)

Also ich habe mich wahrscheinlich ungenau erklärt. Naja - da ich eben von c komme und mir includen schon klar ist. In c wird ja einfach nur Code (Funktionen, Strukturen, etc.), den man in einer anderen Header-Datei (oder wo auch immer) benötigt, eingebunden, damit er dem Compiler dann bekannt ist und auch verwendet werden kann.

In C++ gibt es ja eben auch noch diese namespaces und - viel wichtiger - hier sollte ja alles strukturierter und abgeschlossener sein.

Ich erkläre am besten mal an einem Beispiel, was mir (vielleicht, weil c bei mir einfach zu tief drin sitzt *g*) immer wieder passiert:

Ich habe zwei Klassen (in je einer Header-Datei):
Lokale (Klassen, die sich um die Lokalisierung kümmern)
Events (Eigene Event-Klasse, abgeleitet und erweitert - also meine Application Events quasi)

Nun sollen die
a) schon einmal in allen Headern bekannt sein, da Lokale und Events ja wirklich überall benötigt werden. Dafür habe ich mit static gearbeitet und (gehört vielleicht nicht zum guten C++ Ton) sogar delegates auf nicht statische Methoden erstellt, um diese dann dennoch quasi "static" überall aufrufen zu können, ohne das ein evtl. instantiiertes Objekt bekannt ist.
b) diese beiden Header (also die Klassen darin) brauchen sich gegenseitig. Also die Lokale Klassen sollten durchaus ein Event aus der Event Header-Datei werfen können und die Events sollten lokalisiert sein *g*

EDIT: Hier stand etwas von gegenseitigen Includes. Das ist natürlich unmöglich. Weil Intellisense mir dann in beiden Dateien die jeweils anderen Klassen zur Verfügung gestellt hat, heisst das noch lange nicht, dass das auch richtig so ist.
Klar könnte ich nun beide Header (also Lokale.h und Events.h) in eine Datei packen, aber das ist ja nicht der Sinn der Sache, oder? Es sollen daraus ja über die Zeit hinweg, mehr oder weniger, unabhängige Klassen entstehen (oder eben Klassengemeinschaften *g*).

Ach ein Punkt dazu noch:
Normalerweise kann man ja folgendes machen (also in C++):
Code:
in einem Header:
int i = 5;

dann in einer anderen Datei - ohne obigen Header included zu haben:
extern int i;

i = 7;

Unglücklicherweise geht das ja mit ref classes nicht. Managed Klassen können anscheinend nicht mit extern in einer anderen .h Datei bekannt gemacht werden (zumindest mag das mein Compiler hier nicht ;)) Genauso können sie ja auch nicht global definiert werden, also vor main(). Das sind eben noch einmal weitere Einschränkungen und mich würde interessieren, wie ihr die umgeht bzw. mit diesen Einschränkungen umgeht.

Also es geht mir rein um die Struktur. Jetzt habe ich es doch - ein Rückfall, ich weiss, so gemacht, wie ich es eben in c gewohnt war (da hat man ja auch teilweise .h Dateien nur erstellt, um dort #include zu strukturieren, die dann wieder included wurden - also eine Art Baumstruktur entwickelt, ohne den Compiler damit unnötig zu strapazieren oder gar zu beleidigen *g*).

Das mit den namespaces ist mir in diesem Kontext noch nicht sooo ganz klar, denn wenn ich z.B. einen eigenen namespace (sagen wir mal namespace Local in Lokale.h) definiere, dann ist der ja auch nur in anderen .h Dateien bekannt, wenn ich Lokale.h direkt oder indirekt included habe, oder nicht? Also bis jetzt war das bei mir so, aber vielleicht mache ich da etwas falsch oder müsste die Header/namespaces noch Visual Studio bekannt machen?

So - ach ja - dann noch die Sache mit der Vererbung. Das ist mir soweit klar. Bin ja von c nach C++ und dann erst nach .net gefahren, also hier gibt es ja keine Mehrfach-Vererbung (also in .net - anders, als in C++). Im obigen Beispiel würde für mich Vererbung da auch komisch aussehen (mal abgesehen, dass dabei immer noch das Problem mit den gegenseitigen Includes bestehen bliebe.

Das mit den Interfaces hört sich sehr gut an - wie würde das denn dann aussehen?

So - jetzt habe ich Krieg und Frieden fertig geschrieben :D und hoffe mal, ihr versteht nun, worum es mir geht ;)

Und vielen Dank schon einmal für eure Antworten :)

Das hier wäre sicherlich auch der Ort für eine allgemeine Diskussion zu dem Thema (vielleicht auch über Patterns, 3Tier, Gang of Four, etc. alles böhmische Dörfer für mich und für viele andere wohl auch ;))
 
Zuletzt bearbeitet:
Wow, netter Aufsatz :D

leitman und ich haben uns kurz angesehen und waren uns einig.
Wir kamen zu dem Entschluss, ein simples WTF würde es wohl am Besten ausdrücken :D

Nichtsdestotrotz sind wir ja alle hier um zu helfen und geholfen zu werden. Leider hab ich wie gesagt von C++ .NET absolut keine Ahnung, und mir is auch nach wie vor nicht so ganz klar was du willst.
Also wenn du das ganze kurz in Pseude-Code klar machen könntest was nun genau das Problem ist und dir eine Lösung in C# nichts ausmachen würde, dann nur her damit :)

Ansonsten muss sich leider leitman weiter damit befassen.

PS:
Macan hat gesagt.:
So - jetzt habe ich Krieg und Frieden fertig geschrieben :D und hoffe mal, ihr versteht nun, worum es mir geht ;)
Also eigentlich bin ich jetzt mehr verwirrt als zuvor....:suspekt:

//edit: Wenn ich mir nochmal deine Grafik her nehme:
Code:
                ------- Datei C -------
Datei D -------|                       |------- Datei A
                ------- Datei B -------

Dann hast du 3 Klassen (D, C, B), wobei B und C von D ableiten. Und A ist ein Objekt einer der beiden Klassen (C, B) und du willst aber auf die Methoden beider Klassen (C UND B, zusätzlich D, da B und C ja von D ableiten) zugreifen, richtig?
 
Zuletzt bearbeitet:
leitman und ich haben uns kurz angesehen und waren uns einig.
Wir kamen zu dem Entschluss, ein simples WTF würde es wohl am Besten ausdrücken
Hehe - warum passiert mir das nur immer :D

Dann hast du 3 Klassen (D, C, B), wobei B und C von D ableiten. Und A ist ein Objekt einer der beiden Klassen (C, B) und du willst aber auf die Methoden beider Klassen (C UND B, zusätzlich D, da B und C ja von D ableiten) zugreifen, richtig?
Nicht ganz. Ich habe zwei Klassen, die einander verwenden, also gegenseitig einige Methoden aufrufen müssen. Eben Events (C) und Lokale (B). Die sollen sich nur gegenseitig kennen, um sich aufrufen zu können. Diese zwei Klassen müssen dann aber auch einer dritten Klasse (A) bekannt sein, da die diese auch kennen und verwenden muss. Also müssen sie sich wohl gegenseitig includen (nicht ableiten), oder geht man da OO noch einen anderen Weg?
Die Klassen stehen hier ja für .h Dateien.
In dem Falle habe ich die static gemacht, also sind sie als Klassen überall (zumindest dort, wo sie via #include bekannt sind), verwendbar (mit static definiert, also müssen sie nicht instantiiert werden, keine Objekte werden). Ohne D funktioniert das ja mit #include, aber wenn dann noch eine .h Datei mit Klasse D hinzukommt, die jeweils Klasse B und C bekannt sein soll, dann wird's haarig.

Aber vielleicht ist das ja nicht der richtige Weg in OOP, das ist eben eine Frage für mich.

Dann gibt es noch das Problem:

Code:
main()
Form^ Win = gcnew Form();
Also hier habe ich ein Objekt Win einer Klasse Form erzeugt.

Jetzt will ich aber das Objekt Bar ausserhalb des Sichtbarkeitsbereiches ansprechen:
Code:
Foo.h
...
Win->Show();
...
Geht natürlich nicht, da Win ja nicht bekannt ist.
Normalerweise macht man dann folgendes (in C++):
Code:
Foo.h
extern Form Win; // müsste eigentlich Form^ heissen, aber mit extern können keine ref classes auf diese Art bekannt gemacht werden - das geht nur mit unmanaged Klassen
Win->Show();
...
Hier finde ich einfach keine Lösung, ausser die Struktur eines - ansich - gut strukturierten Codes, noch einmal grundsätzlich zu verändern.

In c# gibt es wohl einige der Einschränkungen nicht, denke ich. Also es geht nicht um Ableitungen, sondern um den Sichtbarkeitsbereich von Klassendefinitionen und Objekten :)
 
Booooaaahhh... ich hab grade Mörderkopfweh... war gestern ne lange Nacht und jetzt sitz ich schon wieder seit über 8 Stunden vor 4 Monitoren -.-
Kann mich grad überhaupt nicht mehr konzentrieren, aber werde versuchen dir zu helfen,
ansonsten erst morgen wieder okay?

Ich habe zwei Klassen, die einander verwenden, also gegenseitig einige Methoden aufrufen müssen. Eben Events (C) und Lokale (B). Die sollen sich nur gegenseitig kennen, um sich aufrufen zu können. Diese zwei Klassen müssen dann aber auch einer dritten Klasse (A) bekannt sein, da die diese auch kennen und verwenden muss. Also müssen sie sich wohl gegenseitig includen (nicht ableiten), oder geht man da OO noch einen anderen Weg?
Sagt dir das Schlüsselwort "friend" etwas? Damit kannst du Klassen als Freund anderer Klassen festlegen!
Hab ich aber leider selber noch nie verwendet, deshalb kann ich dir auch nicht viel dazu sagen, aber am Besten guXt du MSDN :google:
Oder, wenn du gut in der englischen Sprache bewandert bist, schaust du auf "Codeproject.com" die haben dort für beinahe jedes Problem ne Lösung

Wegen deinem Problem, zu dem du auch den Code gepostet hast...
Versteh ich nicht ganz du erstellst ein Object, klar soweit,
aber wo willst du es dann verwenden? noch in derselben Klasse? oder wenigstens im selben Namespace? :confused: *megakopfwehhab* -.-

Kannst du vl nur ganz kurz und vereinfacht die Struktur deines Projektes posten?
Oder einfach ein neues erstellen, das denselben prinzipiellen Aufbau hat?
Nur dass ich weiß, welche Klassen vorkommen und wie diese miteinander verknüpft sind...
Ich mein, wenn das wirklich nur 4 sin, kann das ja nicht so schwer sein *lol* :p

*Schädelpecken-hört-nicht-auf* *grml* :(

Wegen dem Scope, schau mal weiter, was du finden kannst (MSDN, Google, whatever,...), auch mit globale Variablen (obwohl sowas eher ungern gesehen wird)
und ich bild mir ein, extern gibts immer noch? Nur keine Ahnung wie das verwendet wird :(

sry, muss aufhören, ich glaub mein Schädel platzt gleich

ich geh penn0rn
c ya
 
Zuletzt bearbeitet:
Aua - geh ruhig schlafen, ich muss sowieso auch gleich weg und poste morgen weiter ;)

"friend" gibt es in C++, aber für managed classes ist es nicht erlaubt... leider.
Mit "extern" ist es leider auch so. Das schränkt schon etwas ein.

Also gute Nacht (und Besserung ;)) und danke schonmal für eure Antworten :)
 
Poste wenn möglich doch bitte mal im Pseudo-Code Format (wiki) deinen Projekt Aufbau...

Ich muss bitte zusätzlich wissen wie die Dateien angeordnet sind, also in ob die Klassen in derselben DLL liegen oder nicht.
Wenn nein -> Interface ;)

//edit: Stimmt, Properties sind auch eine Möglichkeit :p
 
Zuletzt bearbeitet:
Also jetzt muss ich mal was einwerfen. Ich sehe das ganze entwickelt sich zu dem Punkt
zu dem ich schon mit Markus selber vià PN gekommen bin. ->Interfaces

Jetzt habe ich mal Zeit gehabt mir mal alles mal genau durchzulesen und stelle fest,
dass es dir wirklich noch an der draufsicht zu der OOP fehlt Markus.
Damit meine ich, dass Du dir Gedanken machst wie Du von einer Sourcedatei zu anderen Objekte ansprechen sollst.
Das ist aber dank Namaspaces kein Problem mehr. Definier die Objekte in den gleichen Namespace
und Du kannst ohne was zu includieren darauf zu greifen. Ansonsten musst die entsprechenden Namespaces einbinden.

Wenn Du auf bereits instanzierte Objekte zugreifen willst, musst sie in der Klasse in der sie definiert wurden
viá Property verfügbar machen und schon kannst auch auf sie zugreifen.

Wie Du die Klassen bereit stellst die diese Objekte halten, ist allerdings wieder eine andere Geschichte.
Das kannst zum einen viá Referenzen lösen, die Du weiter reichst.
Oder viá des Singleton Patterns (Statische Objektdefinitionen und Propertys),
was für deine Event und Localizing Klassen ideal währe.

Wenn Du immer noch nicht damit zurech kommen solltest,
musst vorweg mal mit UMLs und schematischen Darstellungen des gesamten Programaufbaus arbeiten.
Verinnerliche Dir die Zugriffsebenen visuell, damit kommst viel schneller klar und lernst die OOP viel besser auszunutzen.
 

Neue Beiträge

Zurück