Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Given an abstract interface and an implementation derived from that interface, where constructors are protected (creation of these objects only being available from a class factory - to implement a DI pattern), how can I make use of make_shared in the factory function?

For example:

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 obviously cannot access the protected constructor in InterfaceImpl, or indeed in IInterface, giving me the following error


error C2248: 'InterfaceImpl::InterfaceImpl' : cannot access protected member declared in class 'InterfaceImpl'

So reading here (question: How to make boost::make_shared a friend of my class), I tried putting the following into the implementation class:


friend std::shared_ptr<InterfaceImpl> std::make_shared<InterfaceImpl>();

It still wouldn't compile. So then I put another one into the IInterface class too. Still no joy. What have I done wrong here?

EDIT: Full source file used to compile, with "friend"...

#include <memory>

class IInterface
{    
public:    
    friend std::shared_ptr&lt;IInterface> Create();     
    virtual void Method() = 0;
};

class InterfaceImpl : public IInterface
{    
public:     
    virtual void Method() {}

protected:    
    friend std::shared_ptr&lt;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();   
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
594 views
Welcome To Ask or Share your Answers For Others

1 Answer

With VC10 the solution you linked to doesn't work - the construction of the instance of InterfaceImpl doesn't happen in make_shared, but in an internal type in std::tr1::_Ref_count_obj<Ty>::_Ref_count_obj(void).

I'd just make the Create() function a friend in your case and not use make_shared():

class InterfaceImpl : public IInterface {
// ...    
protected:
    friend std::shared_ptr<IInterface> Create();
    InterfaceImpl() {}
};

std::shared_ptr<IInterface> Create() {
    return std::shared_ptr<IInterface>(new InterfaceImpl());
}

... or use a custom make_shared() implementation that you actually can befriend without relying on ugly implementation details.

An alternative would be to use something like this pass-key-idiom:

class InterfaceImpl : public IInterface {
public:
    class Key {
        friend std::shared_ptr<IInterface> Create();
        Key() {}
    };
    InterfaceImpl(const Key&) {}
};

std::shared_ptr<IInterface> Create() {
    std::shared_ptr<IInterface> object = 
        std::make_shared<InterfaceImpl>(InterfaceImpl::Key());
    return object;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...