Pregunta

Estoy tratando de compilar este pedazo de código muy simple

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

¿Qué puedo hacer para hacer que esto funcione sin crear más objetos que sean necesarios o complicar demasiado las cosas ...

¿Fue útil?

Solución

Agregue un par de constructores y un puntero a la clase principal.

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

Necesitas el constructor myList (), por lo que registra instancias de sí mismo con la instancia de la variable miembro de clase interna. Luego necesita el constructor de elementos para almacenar el puntero a la instancia de la clase myList externa. Finalmente, en el método Add, debe hacer referencia a vec en la instancia de myList almacenada.

Como señala Catskul, el constructor del elemento no debe hacer nada con el puntero myList que recibe. También me gustaría decir que aunque esta respuesta es más cercana a la intención original, la respuesta de steveth45 es más cercana a lo que querría hacer en un programa real.

Otros consejos

De esta manera, no está exponiendo directamente a los miembros de su clase. Tu ejemplo parece demasiado archivado. ¿Por qué poner un std :: vector en una clase y luego exponerlo como público?

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 diferencia de Java, los objetos internos en C ++ no tienen acceso a un puntero externo 'este' ... si lo piensas, puede haber casos en los que no haya uno al que hacer referencia.

La solución de

Richard Quirk es la más cercana a C ++

Las clases internas solo están relacionadas por nombre. No puedes referirte al vector en la clase base de esa manera.

Debe mover el vector a la clase interna o guardar una referencia a él.

Si bien esta publicación tiene algunos años, podría ser capaz de agregarle algo útil. Si bien diré que el diseño de la clase en la publicación original no se ve tan bien, hay veces en que es útil tener una clase incorporada para poder acceder a la clase contenedora. Esto se puede hacer fácilmente sin almacenar punteros adicionales. A continuación se muestra un ejemplo. Debería funcionar como lo tomé de un código existente y cambié algunos nombres. La clave es la macro EmbeddorOf. Funciona como un encanto.

////////////////////// .h archivo ////////////////////////// /

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

#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

Puedes simplificar esto mediante la siguiente construcción:

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

¿Realmente por qué no usas el vector STL directamente? De esta manera usted consigue que todos los algoritmos estándar trabajen con el datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top