Nested Class: Declaration und Definition trennen?



  • Hallo,

    folgendes Problem:
    Ich möchte mehrere Nested Klassen in einer Klasse deklarieren und erst danach definieren, jedoch benötige ich von den Nested Klassen jeweils einen Member in der Umschliessenden Klasse, im g++ 4.2.4 bekomme ich dann allerdings die Fehlermeldung:
    error: field 'x' has incomplete type

    Einfaches Example:

    class Outer {
        Outer(){};
        ~Outer(){};
    protected:
        class Nested1;
        class Nested2;
        Nested1 x;
        Nested2 y;
    };
    
    class Outer::Nested1{
        int x;
    };
    
    class Outer::Nested2{
        char z;
    };
    
    int main() {
        Outer a;
    }
    

    Habe ich da etwas falsch verstanden? Im Dokument n2798.pdf zum C++0x ist unter 9.7.3 ein ähnliches Example und an der Stelle sollte sich doch nichts geändert haben zum aktuellen Standard?

    Viele Grüße
    Nested



  • Unterstützt das denn der GCC deiner Version?
    Lad sonst mal die neuste Version runter:
    http://gcc.gnu.org/

    Unterstützen muss er das ja noch nicht.



  • Zu dem Zeitpunkt wo du Variablen (oder Member) einer Klasse deklarierst muss bereits die vollständige Definition der Klasse vorliegen. Anders ists, wenn du nur Pointer oder Referenzen auf ein Objekt der Klasse hast.



  • pumuckl schrieb:

    Zu dem Zeitpunkt wo du Variablen (oder Member) einer Klasse deklarierst muss bereits die vollständige Definition der Klasse vorliegen. Anders ists, wenn du nur Pointer oder Referenzen auf ein Objekt der Klasse hast.

    Ups, ja stimmt natürlich 😞 Ich wollte die Deklaration und Definition halt trennen um die Übersichtlichkeit in der Outer-Klasse zu wahren. Bleibt mir an der Stelle nichts anderes übrig als es innerhalb zu definieren oder mit shared_pointern zu arbeiten.

    Danke jedenfalls 🙂

    @Drakon: ich habe leider den aktuellen Standard momentan nicht zur Hand und da alle Änderungen in n2798 farblich markiert sind, dachte ich es sei im aktuellen Standard an der Stelle identisch. Mea culpa 🙂



  • die farbigen teile in n2798 sind nur diejenigen, die der editor seit dem letzten meeting neu eingearbeitet hat.



  • queer_boy schrieb:

    die farbigen teile in n2798 sind nur diejenigen, die der editor seit dem letzten meeting neu eingearbeitet hat.

    Hätte mir eigentlich klar sein sollen 😞 macht ja auch am meisten Sinn!

    aber nochmal zum Thema ich kann doch die Forward-Deklaration verwenden, wenn ich die Member als Pointer (shared_ptr<>) verwende, empfiehlt es sich die Nested-Klassen dann in eine separate Header-Datei zu schreiben? Was würdet ihr empfehlen?

    Gruß und Danke
    Nested



  • nested schrieb:

    aber nochmal zum Thema ich kann doch die Forward-Deklaration verwenden, wenn ich die Member als Pointer (shared_ptr<>) verwende, empfiehlt es sich die Nested-Klassen dann in eine separate Header-Datei zu schreiben? Was würdet ihr empfehlen?

    Sollen die Nested-Klassen in abgeleiteten Klassen (und protected deuted darauf hin das du Outer als Basisklasse verwendest) bekannt sein? Wenn ja ist die Separierung weniger geeignet.

    Wenn du aber, wie von mir recht häufig gesehen, protected einfach nur zu verschwenderisch verwendest (für mich ist private Standard, liegt auch daran das ich flache Vererbungshierachien bevorzuge), würde ich gar die ganze Implementierung über das Handle-Body Idiom auslagern und die Nested Klassen als Implementierungsdetail garnicht in der sichtbaren Schnittstelle bekannt machen.

    cu André



  • nested schrieb:

    wenn ich die Member als Pointer (shared_ptr<>) verwende, empfiehlt es sich die Nested-Klassen dann in eine separate Header-Datei zu schreiben? Was würdet ihr empfehlen?

    Wenn du sie wie in deinem Code protected machen willst, sollten die Deklarationen in den gleichen Header, damit ableitende Klassen Zugriff darauf haben. Wenn sie private sind sollten die Deklarationen in das .cpp file, da es dann Implementationsdetails sind und niemand sonst Zugriff drauf benötigt.
    Die Deklarationen in eine gesonderte Headerdatei auszulagern halte ich nicht unbedingt für sinnvoll, da ableitende Klassen den sonst immer in die -cpp einbinden müssten, wenn sie etwas mit den beiden membern anstellen wollen.



  • asc schrieb:

    Sollen die Nested-Klassen in abgeleiteten Klassen (und protected deuted darauf hin das du Outer als Basisklasse verwendest) bekannt sein? Wenn ja ist die Separierung weniger geeignet.

    Nein, es soll nicht abgeleitet werden von Outer. Es handelt sich bei Outer um eine Klasse für einen Assistenten (Wizard) und bei den Nested-Klassen um die einzelnen Pages.

    asc schrieb:

    Wenn du aber, wie von mir recht häufig gesehen, protected einfach nur zu verschwenderisch verwendest (für mich ist private Standard, liegt auch daran das ich flache Vererbungshierachien bevorzuge), würde ich gar die ganze Implementierung über das Handle-Body Idiom auslagern und die Nested Klassen als Implementierungsdetail garnicht in der sichtbaren Schnittstelle bekannt machen.

    cu André

    Ja du hast Recht, an der Stelle ist das protected wirklich verschwenderisch. Ich selber versuche auch nur Vererbung einzusetzen wenn es wirklich sein muss (momentan muss ich es oft machen, da ich GUI entwickeln muss 😮 ), da meiner Meinung nach flache Hierachien schöner sind 😉
    Aber ich habe da eine Frage, verwendest du dann immer das Handle-Body Idiom für den private-Teil?

    Gruß
    Nested



  • nested schrieb:

    Ja du hast Recht, an der Stelle ist das protected wirklich verschwenderisch.

    Grundsätzlich habe ich mir die Regel gemacht:
    Default ist private, protected verwende ich Grundsätzlich erst wenn ich
    a) weiß das ich mit Vererbung arbeite
    und
    b) die Methode nochmal auf Sinn in einer Vererbung überprüft habe

    nested schrieb:

    Ich selber versuche auch nur Vererbung einzusetzen wenn es wirklich sein muss (momentan muss ich es oft machen, da ich GUI entwickeln muss 😮 ),

    Ich sehe keinen Zusammenhang zwischen UI-Entwicklung und Vererbung.

    nested schrieb:

    Aber ich habe da eine Frage, verwendest du dann immer das Handle-Body Idiom für den private-Teil?

    Nein.

    Ich verwende das Handle-Body Idiom dann, wenn ich ein aufwendigeres Include dadurch verschieben kann oder die Komplexität wie in deinen Fall höher ist, weil z.B. Innere Klassen verwendet werden.

    cu André


Anmelden zum Antworten