Cyclic Dependencies, Includes, Forward Declarations, Namespaces

Macan

Mitglied
So jetzt :D

Problem:
Klassen in verschiedenen Dateien brauchen sich gegenseitig (müssen sich kennen).
Lösung: Siehe weiter unten (also ich hoffe zumindest, dies ist eine Lösung :D)

Der Thread "Wie includet ihr?" hat mir ja nicht wirklich Erleuchtung (obwohl sich cosmo, leitman und Nil mit mir wirklich Mühe gegeben hatten) gebracht und ich stosse einfach immer wieder auf gewisse Probeme beim designen einer Application.

Wenn man im Netz sucht, dann findet man oft das Problem, aber nie eine Lösung. Da wird es dann schnell akademisch mit "eigentlich gibt es ja keine Forward Declarations, etc.", "also das ist historisch, da in c eben...", "c hatte keine namespaces, ausser eben... struct... typedef..." und noch weniger hilfreiches.

Darum habe ich mich mal hingesetzt und das wirklich laaange durchexerziert (einige hier werden nun sicher schmunzeln und sagen "ach das meinte er - klar geht das so..." oder eben nur "Ja das weiss man doch..." ;)

Also - nachdem im Netz wirklich wenig darüber zu lesen ist (wenig hilfreiches) und auch in den meisten Büchern dieses Thema nur am Rande oder ohne wirklich komplexere Beispiele behandelt wird - dachte ich mir, ich poste das mal.

Es wäre schön, wenn hier einige etwas dazu sagen würden, denn ich weiss nicht, in wie weit mein Beispiel mit sinnvoller C++ Programmierung konform geht. Aber immerhin gibt es in diesem Beispiel nichts globales (static, singleton, etc.) und alles ist schön getrennt.

Ach noch etwas: Ich weiss ja, dass das eigentlich schon mehr ein C++ Posting ist, aber immerhin gibt es Gründe, das auch speziell unter .net zu behandeln:
1. Wenn man in MSDN unter dem Schlüsselwort "extern" sucht, dann findet man das hier:
http://msdn2.microsoft.com/en-gb/library/0603949d.aspx
http://msdn2.microsoft.com/en-us/library/061kwye0.aspx
und das kann einem als Neuling schon grosses Kopfzerbrechen bereiten, da man nun wirklich nur mit "extern" versucht, Probleme zu lösen.
2. Wird eben (also ich habe wirklich nichts in der MSDN gefunden) die pure Forward Declaration wohl als nicht erklärenswert angesehen. Gleichzeitig führen "normale" "extern" Deklarationen und normale Forward Deklarationen (gerade, wenn es um Klassen und deren Member geht) den Compiler immer zu der Annahme, dass es sich hier um eine globale Variable, etc. handelt (das dürfte .net-spezifisch sein).
3. Ist hier mit #pragma das ewige (anscheinend auch nicht C++ konforme) #ifdef, #define obsolet und es sieht gleich alles viel schöner aus :D
4. Ich weiss nicht, ob das auch unter anderen C++ Compilern zu ähnlichen Ergebnissen führen würde, aber da sind noch die namespaces (zu denen komme ich gleich).

Die Namespaces sollten ja einiges vereinfachen. In der Tat ist das ja auch so, aber wer sich den Sourcecode mal ansieht, der wird etwas sehen, wie:
Code:
namespace Foo {ref class Bar;}
Bis zu einem gewissen Punkt ging alles ohne dieses Konstrukt, aber irgendwann produzierte ein Compilerlauf (wegen fehlender Includes bzw. zu vielen cyclischen Abhängigkeiten) nur noch "Namespace Foo unbekannt" Meldungen. Mit obigen Trick(?) lässt sich das umgehen.

So - war wieder mal lang. Also ich bin mal gespannt, was andere hier dazu sagen. Hoffentlich ist mein Beispiel einigermassen sinnvoll :D

Das Beispiel ist zu lang, um es hier direkt zu posten - also hier ist die .zip Datei. Falls von mir versuchtes Sinn macht, kann ich es ja noch mit Kommentaren versehen, etc.
 

Anhänge

  • 27189attachment.zip
    16,8 KB · Aufrufe: 19
Zuletzt bearbeitet:
Ähm... dafür, dass dies so eine (für mich) harte Nuss war... wird es jetzt immer einfacher.

Code:
#pragma once
// Hier dann weitere Includes, die einmalig benötigt werden

// ab hier dann immer nach diesem Muster
#include "Foo.h"
namespace Foos {ref class Bar;}
using namespace Bars;
#include "FooBar.h"
namespace FooBars {ref class BarFoo;}
using namespace FooBars;
// und so weiter, immer nach obigen Muster

// ab hier dann die normalen namespaces
using namespace System;
// ...
Ich habe nun mit einigen Headern mehrfache Forward Referenzen erzeugt und alles ist gut. Ausserdem werden auch immer nur die geänderten Dateien neu compiliert (also auch hier stimmt noch alles).
Einfach nach obigem Muster alles benötigte in andere Header referenzieren.
 
Zurück