C++ 通过基类';仅将对象创建为共享指针;创建'-方法
我试图通过调用一个名为“create”的静态方法来实现应用程序中的某些对象只能被构造为共享的\u ptr 当然,我可以通过直接将静态“create”方法添加到所有相应的类中来实现这一点。然而,这意味着我必须在几乎所有的类中重复非常相似的代码。宏可以工作,但我觉得这不是很优雅 我想出了另一种方法,从实现“create”方法并返回指针的模板化“BaseObject”类派生所有类。除了std::make_shared在受保护时无法访问其子类的构造函数之外,这几乎是可行的 非解决方案是将子类构造函数公开(请参见下面示例中的(1))。但是现在Foo可以正常地重新构造,这将破坏整个要点。另一种解决方案是在子类中建立BaseObject的好友关系,并直接使用shared_ptr(参见示例中的(2)) 这两种解决方案都给子类的实现者带来了额外的负担。因为他们必须找到一种使构造函数非公共的替代方法,或者放置一个友元声明。(2)解决方案还有一个问题,即无法使用更高效的make_共享 我的问题是:有没有更好的方法C++ 通过基类';仅将对象创建为共享指针;创建'-方法,c++,c++11,constructor,shared-ptr,C++,C++11,Constructor,Shared Ptr,我试图通过调用一个名为“create”的静态方法来实现应用程序中的某些对象只能被构造为共享的\u ptr 当然,我可以通过直接将静态“create”方法添加到所有相应的类中来实现这一点。然而,这意味着我必须在几乎所有的类中重复非常相似的代码。宏可以工作,但我觉得这不是很优雅 我想出了另一种方法,从实现“create”方法并返回指针的模板化“BaseObject”类派生所有类。除了std::make_shared在受保护时无法访问其子类的构造函数之外,这几乎是可行的 非解决方案是将子类构造函数公开
template<class T>
class BaseObject
{
public:
typedef std::shared_ptr<T> SharedPtr;
template<class... Args>
static typename BaseObject<T>::SharedPtr create(Args&&... args)
{
return std::make_shared<T>(args...);
//return std::shared_ptr<T>(new T(args...)); (2)
}
};
class Foo : public BaseObject<Foo>
{
//friend BaseObject<Foo>; (2)
protected: //public (1)
Foo(int a = 0) : m_foo(a) {}
private:
int m_foo;
};
int main(int argc, char* argv[])
{
Foo::SharedPtr bla = Foo::create(1);
return 0;
}
模板
类基类对象
{
公众:
typedef std::shared_ptr SharedPtr;
模板
静态typename BaseObject::SharedPtr创建(Args&&…Args)
{
返回std::使_共享(args…);
//返回std::shared_ptr(新的T(参数…);(2)
}
};
类Foo:publicbaseObject
{
//友元对象;(2)
受保护公众(1)
Foo(int a=0):m_Foo(a){}
私人:
林文福,;
};
int main(int argc,char*argv[])
{
Foo::SharedPtr bla=Foo::create(1);
返回0;
}
更新:
他们传递的关键习语似乎为我此刻提供了最好的解决方案:
template<class T>
class BaseObject
{
public:
typedef std::shared_ptr<T> SharedPtr;
class Key
{
friend class BaseObject<T>;
Key() {}
};
template<class... Args>
static typename BaseObject<T>::SharedPtr create(Args&&... args)
{
return std::make_shared<T>(Key(), args...);
}
};
class Foo : public BaseObject<Foo>
{
public:
Foo(BaseObject<Foo>::Key, int a = 0) : m_foo(a) {}
private:
int m_foo;
};
模板
类基类对象
{
公众:
typedef std::shared_ptr SharedPtr;
类密钥
{
友元类基本对象;
键(){}
};
模板
静态typename BaseObject::SharedPtr创建(Args&&…Args)
{
返回std::make_shared(Key(),args…);
}
};
类Foo:publicbaseObject
{
公众:
Foo(BaseObject::Key,int a=0):m_Foo(a){}
私人:
林文福,;
};
好处是:
- 只能通过以下方式将Foo对象创建为共享\u ptr Foo::创建
- 无需在Foo中添加复杂的好友声明
- std::make_shared仍然有效李>
此解决方案的唯一问题是需要将“Key”作为构造函数中的第一个参数。但我可以接受 更好是主观的,但我相信如果您将构造函数设置为私有,并将
std::make_shared
设置为友元函数,会更直观一些。这样,唯一可以创建对象的函数就是std::make_shared
,您可以编写
std::shared_ptr<Foo> ptr = std::make_shared<Foo>(12);
因此,任何未来的代码读者都可以理解您的意思,而无需实际查看Foo
类
更新
我尝试过我写的东西,但没有真正起作用。下面是一个类似问题的答案,很可能也适用于您的问题:
更新2
下面是如何让它工作的(VC++2013)
#包括
使用名称空间std;
福班
{
受保护的:
Foo(int a=0):m_Foo(a){}
私人:
林文福,;
好友共享\u ptr make_shared();
朋友类(参考)(计数)对象;;
};
int main()
{
共享的\u ptr foo=使\u共享(12);
返回0;
}
\u Ref\u count\u obj
是由使共享
内部使用的,这就是为什么您也需要与之成为朋友。此外,您还应该从启用共享这一点派生。请参阅此处的详细信息:@Sarang是的,如果他愿意使用boost,但在他的示例中,它确实是一个STL共享指针。@GáborAngyal感谢您的回答。这个解决方案的主要问题是friend'ing std::make_shared将是非常特定于实现的。对VC++标准库的更新可能会破坏所有代码,并且需要在libc++和libstdc++上完全不同的代码。从用户和维护的角度来看,这对我来说是行不通的。但如果你声明make_shared为好友,那么你就允许everywhere创建对象实例作为共享指针。
Foo::SharedPtr bla = Foo::create(1);
#include <memory>
using namespace std;
class Foo
{
protected:
Foo(int a = 0) : m_foo(a) {}
private:
int m_foo;
friend shared_ptr<Foo> make_shared<>();
friend class _Ref_count_obj<Foo>;
};
int main()
{
shared_ptr<Foo> foo = make_shared<Foo, int>(12);
return 0;
}