Question

j'essaie de compiler ce morceau de code très 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");
}

Que puis-je faire pour que cela fonctionne sans créer plus d'objets qui auraient besoin ou sans compliquer les choses ...

Était-ce utile?

La solution

Ajoutez quelques constructeurs et un pointeur à la classe parent.

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

Vous avez besoin du constructeur myList (). Il enregistre donc ses instances avec l'instance de la variable membre de la classe interne. Ensuite, vous avez besoin du constructeur Items pour stocker le pointeur sur l'instance de classe myList externe. Enfin, dans la méthode Add, vous devez référencer vec dans l'instance stockée myList.

Comme le souligne Catskul, le constructeur Item ne doit rien faire avec le pointeur myList qu’il reçoit. Je voudrais également dire que même si cette réponse est plus proche de l'intention initiale, la réponse de steveth45 est plus proche de ce que vous voudriez faire dans un programme réel.

Autres conseils

De cette façon, vous n'exposez pas directement les membres de votre classe. Votre exemple semble un peu trop architecturé. Pourquoi mettre un std :: vector dans une classe et ensuite l'exposer comme public?

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

Contrairement à Java, les objets internes en C ++ n'ont pas accès à un pointeur externe 'this' ... si vous y réfléchissez, il peut arriver qu'il n'y en ait aucun à référencer.

La solution de Richard Quirk est la plus proche que vous puissiez obtenir en C ++

Les classes internes ne sont liées que par leur nom. Vous ne pouvez pas faire référence au vecteur dans la classe de base comme ça.

Vous devez déplacer le vecteur dans la classe interne ou stocker une référence à celle-ci.

Bien que ce message date de quelques années, je pourrais pouvoir lui ajouter quelque chose d’utile. Bien que je dirais que la conception de la classe dans l'article d'origine n'est pas très belle, il est parfois utile de faire en sorte qu'une classe incorporée puisse accéder à la classe qui la contient. Cela peut facilement être fait sans stocker des pointeurs supplémentaires. Voici un exemple. Cela devrait fonctionner comme je l'ai pris à partir d'un code existant et changer quelques noms. La clé est la macro EmbeddorOf. Fonctionne comme un charme.

////////////////////// fichier .h ////////////////////////////// /

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

////////////////// fichier .cpp ///////////////////

#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

Vous pouvez simplifier cela avec la construction suivante:

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

Pourquoi n'utilisez-vous pas directement le vecteur STL? De cette façon, tous les algorithmes standard fonctionnent avec le données.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top