videos programar programacion poo orientado orientada objetos objeto net como clases ats anidadas c++ class nested

c++ - programar - vb net clases anidadas



Las clases anidadas de C++ me vuelven loco (6)

Estoy tratando de compilar esta pieza muy simple de código

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 que esto funcione sin crear más objetos que necesiten o cosas complicadas?


A diferencia de Java, los objetos internos en C ++ no tienen acceso a un puntero "this" externo ... si lo piensas, puede haber casos en los que no haya ninguno para hacer referencia.

La solución de Richard Quirk es la más cercana que puede obtener en C ++


De esta manera, no expones a los miembros de tu clase directamente. Tu ejemplo parece demasiado arquitectónico un poco. ¿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"); }


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

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

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


Puede simplificar esto mediante la siguiente construcción:

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

¿De verdad por qué no usas el vector STL directamente? De esta forma, obtienes todos los algoritmos estándar que funcionan con los datos.


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

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

//////////////// archivo .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; }

Mella


Las clases internas solo están relacionadas por nombre. No puede referirse al vector en la clase base así.

O necesita mover el vector a la clase interna o almacenar una referencia a él.