Domanda

Sto cercando di compilare questo semplicissimo pezzo di codice

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");
}

cosa posso fare per farlo funzionare senza creare più oggetti necessari o cose complicate ...

È stato utile?

Soluzione

Aggiungi un paio di costruttori e un puntatore alla classe genitore.

#include <string>
#include <vector>
class myList
{
public:
    std::vector<std::string> vec;
    myList(): items(this) {} // Added
    class Items
    {
    public:
        Items(myList *ml): self(ml) {}  // Added
        void Add(std::string str)
        {
                self->vec.push_back(str); // Changed
        };
        myList *self; //Added
    }items;
};

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

È necessario il costruttore myList (), quindi registra le istanze di se stesso con l'istanza della variabile membro della classe interna. Quindi è necessario il costruttore Items per memorizzare il puntatore all'istanza della classe myList esterna. Infine nel metodo Aggiungi, è necessario fare riferimento a vec nell'istanza myList memorizzata.

Come sottolinea Catskul, il costruttore Item non deve fare nulla con il puntatore myList che riceve. Vorrei anche dire che sebbene questa risposta sia più vicina all'intento originale, la risposta di steveth45 è più vicina a ciò che vorresti fare in un vero programma.

Altri suggerimenti

In questo modo non stai esponendo direttamente i membri della tua classe. Il tuo esempio sembra un po 'sovra-progettato. Perché mettere uno std :: vector in una classe e poi esporlo come pubblico?

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");
}

A differenza di Java, gli oggetti interni in C ++ non hanno accesso a un puntatore 'this' esterno ... se ci pensate, potrebbero esserci casi in cui non ce n'è uno a cui fare riferimento.

La soluzione di Richard Quirk è la più vicina che puoi trovare in C ++

Le classi interne sono correlate solo per nome. Non puoi fare riferimento al vettore nella classe base in questo modo.

Devi spostare il vettore nella classe interna o memorizzare un riferimento ad esso.

Mentre questo post ha qualche anno, potrei essere in grado di aggiungere qualcosa di utile. Mentre dirò che il design della classe nel post originale non sembra così bello, ci sono volte in cui è utile avere una classe incorporata in grado di accedere alla classe contenente. Questo può essere fatto facilmente senza memorizzare ulteriori puntatori. Di seguito è riportato un esempio. Dovrebbe funzionare come l'ho preso da un codice esistente e ho cambiato alcuni nomi in giro. La chiave è la macro EmbeddorOf. Funziona come un fascino.

//////////////////// .h file //////////////////////// /

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 file /////////////////

#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

Puoi semplificarlo con il seguente costrutto:

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

Davvero perché non usi direttamente il vettore STL? In questo modo puoi far funzionare tutti gli algoritmi standard con i dati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top