una resueltos programacion poo orientada objetos miembros ejercicios ejemplo derivadas derivada constructores codigo clases clase c++ friend

c++ - resueltos - Cómo propagar amigo para clases derivadas.



constructores c++ (7)

Como ya han dicho otros, la amistad no es heredable.

Esto parece un buen candidato del patrón "Abstract Factory".

Supongamos que "SomeClass" es derivado poliméricamente de base. declarar una base de fábrica abstracta, que crea objetos Base. derive cada fábrica de concreto desde la base, anule el método de creación de la base ...

vea http://en.wikipedia.org/wiki/Abstract_factory_pattern para ver ejemplos

Quiero tener una jerarquía de clases y poder crear objetos a partir de ella solo dentro de una fábrica.

Ejemplo:

class Base { protected: Base(){}; virtual void Init(){}; friend class Factory; }; class SomeClass : public Base { public://I want protected here! Now it''s possible to call new SomeClass from anywhere! SomeClass(){}; void Init(){}; }; class Factory { public: template<class T> T* Get() { T* obj = new T(); obj->Init(); return obj; } }; int main() { Factory factory; SomeClass *obj = factory.Get<SomeClass>(); }

Mi problema es que quiero poder hacer objetos solo desde Factory, pero no quiero declarar friend class Factory en cada clase derivada de Base.

¿Hay alguna manera de propagar amigo en clases derivadas? ¿Hay alguna otra manera de lograr este comportamiento?


La amistad no es hereditaria ni transitiva, como se describe aquí: clase de amigo con herencia .

Después de un poco de experimentación y de hacer uso de este truco ¿Cómo configurar un contenedor global (C ++ 03)? Creo que he encontrado una forma de otorgar a la "fábrica" ​​derechos únicos para crear los objetos.

Aquí hay un código rápido y sucio. (Desplácese hacia la parte inferior para ver el truco).

class Object {}; class Factory { public: // factory is a singleton // make the constructor, copy constructor and assignment operator private. static Factory* Instance() { static Factory instance; return &instance; } public: typedef Object* (*CreateObjectCallback)(); private: typedef std::map<int, CreateObjectCallback> CallbackMap; public: // Derived classes should use this to register their "create" methods. // returns false if registration fails bool RegisterObject(int Id, CreateObjectCallback CreateFn) { return callbacks_.insert(CallbackMap::value_type(Id, createFn)).second; } // as name suggests, creates object of the given Id type Object* CreateObject(int Id) { CallbackMap::const_iterator i = callbacks_.find(Id); if (i == callbacks_.end()) { throw std::exception(); } // Invoke the creation function return (i->second)(); } private: CallbackMap callbacks_; }; class Foo : public Object { private: Foo() { cout << "foo" << endl; } private: static Object* CreateFoo() { return new Foo(); } public: static void RegisterFoo() { Factory::Instance()->RegisterObject(0, Foo::CreateFoo); } }; class Bar : public Object { private: Bar() { cout << "bar" << endl; } private: static Object* CreateBar() { return new Bar(); } public: static void RegisterBar() { Factory::Instance()->RegisterObject(1, Bar::CreateBar); } }; // use the comma operator hack to register the create methods int foodummy = (Foo::RegisterFoo(), 0); int bardummy = (Bar::RegisterBar(), 0); int main() { Factory::Instance()->CreateObject(0); // create foo object Factory::Instance()->CreateObject(1); // create bar object }


No es posible. Como han dicho otros, la amistad no se hereda.

Una alternativa es hacer que todos los constructores de jerarquía de clases estén protegidos y agregar la función / clase de fábrica como amigo a todas las clases en las que esté interesado.



No, es deliberadamente imposible.

Es un problema por encapsulación.

Supongamos que tenemos una clase "PswClass" que administra cualquier contraseña, es decir, un amigo en cascada con otra clase: si heredo de PswClass:

class Myclass : public PswClass { ....... }

De esta manera, tal vez pueda tener acceso al campo que sería privado.


No, no hay forma de heredar la declaración de friend de la clase base. Sin embargo, si hace que el constructor de Base private , no será posible crear instancias de clases derivadas sin la ayuda de Factory .


Para referencia futura, otra idea que surgió del chat entre OP y yo, que funciona con un solo uso de friend como el OP quería. Por supuesto, esta no es una solución universal, pero puede ser útil en algunos casos.

Debajo del código hay un mínimo que muestra las ideas esenciales. Esto debe estar "integrado" en el resto del código de Factory .

class Factory; class Top { // dummy class accessible only to Factory private: Top() {} friend class Factory; }; class Base { public: // force all derived classes to accept a Top* during construction Base(Top* top) {} }; class One : public Base { public: One(Top* top) : Base(top) {} }; class Factory { Factory() { Top top; // only Factory can create a Top object One one(&top); // the same pointer could be reused for other objects } };