Data un'interfaccia astratta e un'implementazione derivata da tale interfaccia, in cui i costruttori sono protetti (creazione di questi oggetti che sono disponibili solo da un factory di classe - per implementare un modello DI), come Faccio uso di make_shared nella funzione di fabbrica?Uso di make_shared con un costruttore protetto + interfaccia astratta
Ad esempio:
class IInterface
{
public:
virtual void Method() = 0;
};
class InterfaceImpl : public IInterface
{
public:
virtual void Method() {}
protected:
InterfaceImpl() {}
};
std::shared_ptr<IInterface> Create()
{
std::shared_ptr<IInterface> object = std:: make_shared<InterfaceImpl>();
return object;
}
make_shared, ovviamente, non può accedere il costruttore protetto in InterfaceImpl, o addirittura in IInterface, dandomi il seguente errore
error C2248: 'InterfaceImpl::InterfaceImpl' : cannot access protected member declared in class 'InterfaceImpl'
Quindi leggere qui (domanda: How to make boost::make_shared a friend of my class), Ho provato a mettere quanto segue nella classe di implementazione:
friend std::shared_ptr<InterfaceImpl> std::make_shared<InterfaceImpl>();
Ancora non verrebbe compilato. Quindi ne inserisco un altro nella classe IInterface. Ancora nessuna gioia. Cosa ho fatto di sbagliato qui?
EDIT: il file sorgente completo utilizzato per la compilazione, con "amico" ...
#include <memory>
class IInterface
{
public:
friend std::shared_ptr<IInterface> Create();
virtual void Method() = 0;
};
class InterfaceImpl : public IInterface
{
public:
virtual void Method() {}
protected:
friend std::shared_ptr<IInterface> Create();
InterfaceImpl() {}
};
std::shared_ptr<IInterface> Create()
{
std::shared_ptr<IInterface> object = std::make_shared<InterfaceImpl>();
return object;
}
void main()
{
std::shared_ptr<IInterface> i = Create();
}
Immagino che sia VC10? GCC btw non ha problemi finché tu fai amicizia con 'make_shared()'. –
È VS2010, che in realtà fornisce un avviso (erroneamente - dettagliato qui: http://connect.microsoft.com/VisualStudio/feedback/dettagli/321.690/c-VC9-falso-allarme-c4396-per-valido codice). – Robinson