2008-10-25 9 views
12

Ich versuche, dieses sehr einfaches Stück Code zu kompilierenC++ Verschachtelte Klassen mich fahren verrückt

class myList 
{ 
public: 
    std::vector<std::string> vec; 
    class Items 
    { 
    public: 
     void Add(std::string str) 
     { 
      myList::vec.push_back(str); 
     }; 
    }items; 
}; 

int main() 
{ 
    myList newList; 
    newList.items.Add("A"); 
} 

was kann ich tun, um diese Arbeit zu machen, ohne weitere Objekte zu erstellen, die Sachen benötigt oder overcomplicating ...

+3

von Java kommend :-) –

Antwort

15

Fügen Sie ein paar Konstruktoren und einen Zeiger auf die Elternklasse hinzu.

Sie benötigen den Konstruktor myList(), sodass er Instanzen von sich selbst mit der Instanz der inneren Klassenmitgliedsvariablen registriert. Dann benötigen Sie den Items-Konstruktor, um den Zeiger auf die äußere myList-Klasseninstanz zu speichern. Schließlich müssen Sie in der Add-Methode auf vec in der gespeicherten myList-Instanz verweisen.

Wie Catskul darauf hinweist, darf der Item-Konstruktor mit dem empfangenen myList-Zeiger nichts tun. Ich möchte auch sagen, dass, obwohl diese Antwort näher an der ursprünglichen Absicht ist, die Antwort von steveth45 näher an dem liegt, was Sie in einem echten Programm tun möchten.

+0

vielen Dank, das funktioniert, aber ich hatte gehofft, dass ein Einfachere Version existiert, aber ich muss weiter mit C++ - Sturheit umgehen :-(hoffe, C++ 0x löst einige dieser Macken – SMeyers

+1

... aber sei vorsichtig mit der Übergabe der MyList dieser Zeiger, während MyList noch konstruiert wird. Der Items-Konstruktor kann sich selbst in Schwierigkeiten zu bringen, wenn es irgendwas macht, das den MyList diesen Zeiger zu früh benutzt – Catskul

11

Auf diese Weise geben Sie Ihre Klassenmitglieder nicht direkt aus. Ihr Beispiel scheint ein wenig überbearbeitet zu sein. Warum sollte man einen std :: vector in eine Klasse einfügen und dann als public ausgeben?

class myList 
{ 
private: 
    std::vector<std::string> vec; 
public: 
    void Add(std::string str) 
    { 
     vec.push_back(str); 
    }; 
}; 

int main() 
{ 
    myList newList; 
    newList.Add("A"); 
} 
+2

Der ursprüngliche Autor braucht wahrscheinlich das innere Klassenkonstrukt für andere Dinge, die er nicht erwähnt (zur Vereinfachung seiner Darstellung) sind ingenieurtechnische Aspekte der vorhandenen Informationen gegeben, aber das Problem scheint wie ein "Spielzeug" abstrahierende Kompilierung Probleme für könnte ursprünglich ein ziemlich komplexer Algorithmus gewesen sein. Es ist nicht wirklich wichtig, du verstehst wahrscheinlich schon, ich sage nur ... –

2

Die inneren Klassen sind nur mit Namen verknüpft. Sie können nicht so auf den Vektor in der Basisklasse verweisen.

Sie müssen entweder den Vektor in die innere Klasse verschieben oder einen Verweis darauf speichern.

5

Im Gegensatz zu Java haben innere Objekte in C++ keinen Zugriff auf einen äußeren "This" -Zeiger ... Wenn Sie darüber nachdenken, kann es Fälle geben, in denen es keinen Verweis gibt.

Richard Quirk-Lösung ist der nächste Sie C++

0

bekommen können Sie können dies durch das folgende Konstrukt vereinfachen:

typedef std::vector<std::string> myList; 

wirklich, warum Sie die STL-Vektor nicht direkt verwenden? Auf diese Weise erhalten Sie alle Standard-Algorithmen arbeiten mit den Daten.

1

Während dieser Beitrag ein paar Jahre alt ist, kann ich möglicherweise in der Lage sein, etwas nützliches hinzuzufügen. Während ich sagen werde, dass das Design der Klasse im ursprünglichen Post nicht so gut aussieht, gibt es Zeiten, in denen es nützlich ist, dass eine eingebettete Klasse auf die enthaltene Klasse zugreifen kann. Dies kann leicht durchgeführt werden, ohne zusätzliche Zeiger zu speichern. Unten ist ein Beispiel. Es sollte funktionieren, da ich es aus einem bestehenden Code genommen habe und einige Namen geändert habe. Der Schlüssel ist das EmbeddorOf-Makro. Klappt wunderbar.

///////////////////// .h Datei ///////////////////////// //

struct IReferenceCounted 
{ 
    virtual unsigned long AddRef() = 0; 
    virtual unsigned long Release() = 0; 
}; 

struct IFoo : public IReferenceCounted 
{ 
}; 

class Foo : public IFoo 
{ 
public: 
    static IFoo* Create(); 
    static IFoo* Create(IReferenceCounted* outer, IReferenceCounted** inner); 

private: 
    Foo(); 
    Foo(IReferenceCounted* outer); 
    ~Foo(); 

    // IReferenceCounted 

    unsigned long AddRef(); 
    unsigned long Release(); 

private: 
    struct EIReferenceCounted : IReferenceCounted 
    { 
     // IReferenceCounted 

     unsigned long AddRef(); 
     unsigned long Release(); 
    } _inner; 

    unsigned long _refs; 
    IReferenceCounted* _outer; 
}; 

/////////////////.CPP-Datei /////////////////

#include <stdio.h> 
#include <stddef.h> 
#include "Foo.h" 

#define EmbeddorOf(class, member, this) \ 
    (class *) ((char *) this - offsetof(class, member)) 

// Foo 

Foo::Foo() : _refs(1), _outer(&this->_inner) 
{ 
} 

Foo::Foo(IReferenceCounted* outer) : _refs(1), _outer(outer) 
{ 
} 

Foo::~Foo() 
{ 
    printf("Foo::~Foo()\n"); 
} 

IFoo* Foo::Create() 
{ 
    return new Foo(); 
} 

IFoo* Foo::Create(IReferenceCounted* outer, IReferenceCounted** inner) 
{ 
    Foo* foo = new Foo(outer); 
    *inner = &foo->_inner; 
    return (IFoo*) foo; 
} 

// IReferenceCounted 

unsigned long Foo::AddRef() 
{ 
    printf("Foo::AddRef()\n"); 
    return this->_outer->AddRef(); 
} 

unsigned long Foo::Release() 
{ 
    printf("Foo::Release()\n"); 
    return this->_outer->Release(); 
} 

// Inner IReferenceCounted 

unsigned long Foo::EIReferenceCounted::AddRef() 
{ 
    Foo* pThis = EmbeddorOf(Foo, _inner, this); 
    return ++pThis->_refs; 
} 

unsigned long Foo::EIReferenceCounted::Release() 
{ 
    Foo* pThis = EmbeddorOf(Foo, _inner, this); 
    unsigned long refs = --pThis->_refs; 
    if (refs == 0) 
     { 

     // Artifically increment so that we won't try to destroy multiple 
     // times in the event that our destructor causes AddRef()'s or 
     // Releases(). 

     pThis->_refs = 1; 
     delete pThis; 
     } 
    return refs; 
} 

Nick

Verwandte Themen