将 make_shared 与受保护的构造函数一起使用 +抽象接口
给定一个抽象接口和一个从该接口派生的实现,其中构造函数受到保护(这些对象的创建只能从类工厂中获得 - 以实现 DI 模式),我如何在工厂函数中使用 make_shared ?
例如:
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 显然无法访问 InterfaceImpl 中的受保护构造函数,或者确实无法访问 IInterface 中的受保护构造函数,从而出现以下错误
error C2248: 'InterfaceImpl::InterfaceImpl' : cannot access protected member declared in class 'InterfaceImpl'
因此请阅读此处(问题:如何使 boost::make_shared 成为我班级的朋友),我尝试将以下内容放入实现类中:
friend std::shared_ptr<InterfaceImpl> std::make_shared<InterfaceImpl>();
它仍然不会编译。然后我也将另一个放入 IInterface 类中。还是没有喜悦。我在这里做错了什么?
编辑:用于编译的完整源文件,带有“朋友”...
#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();
}
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<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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 VC10,您链接到的解决方案不起作用 -
InterfaceImpl
实例的构造不会发生在make_shared
中,而是发生在std 中的内部类型中::tr1::_Ref_count_obj::_Ref_count_obj(void)
。在您的情况下,我只是将
Create()
函数设为friend
,并且不使用make_shared()
:...或者使用自定义的 make_shared() 实现,您实际上可以在不依赖丑陋的实现细节的情况下与它成为朋友。
另一种方法是使用类似的 pass-key -习语:
With VC10 the solution you linked to doesn't work - the construction of the instance of
InterfaceImpl
doesn't happen inmake_shared
, but in an internal type instd::tr1::_Ref_count_obj<Ty>::_Ref_count_obj(void)
.I'd just make the
Create()
function afriend
in your case and not usemake_shared()
:... 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:
对于最初的问题, std::make_shared<...>() 不会直接实例化您的类,因此,正如您发现的那样,提供对它的朋友访问不会产生任何好处。您可以简单地为朋友提供对直接使用受保护构造函数的代码的访问权限,如下所示:
或者在您的情况下:
这适用于 VS2010 中的 Microsoft 编译器,但看起来它可能是特定于环境的,因为它不适用于 gcc Linux。对于 gcc,std::tr1 命名空间不存在,因此它必须特定于 std 库的 Microsoft 实现。
我的正常工作环境是 Intel 12.1 编译器,它似乎有一个错误,根本不检查访问权限,并且在没有任何友元声明的情况下愉快地构建代码。
To the original question, std::make_shared<...>() does not directly instantiate your class, so providing friend access to it yields no benefit, as you found. You can simply provide friend access to the code that does directly use your protected constructor as follows:
or in your case:
This works with the Microsoft compiler in VS2010, but it looks like it may be environment specific as it does not work with gcc on Linux. With gcc the std::tr1 namespace does not exist, so it must be specific to the Microsoft implementation of std library.
My normal working environment is the Intel 12.1 compiler, which appears to have a bug that does not check for access at all, and happily builds code without any friend declaration.