我一直在研究一种方法来防止用户使用没有智能指针的类。因此,迫使它们使用智能指针对对象进行堆分配和管理。为了得到这样的结果,我尝试了以下方法:
#include <memory>
class A
{
private :
~A {}
// To force use of A only with std::unique_ptr
friend std::default_delete<A>;
};
如果您只希望您的类用户能够通过std::unique_ptr
操作您的类的实例,则此工作非常好。但对std::shared_ptr
不起作用。所以我想知道你是否有什么办法能得到这样的行为。我发现的唯一解决方案是做以下(使用friend std::allocator_traits<A>;
是不够的):
#include <memory>
class A
{
private :
~A {}
// For std::shared_ptr use with g++
friend __gnu_cxx::new_allocator<A>;
};
但是这个解决方案是不可移植的。也许我做错了。
创建一个返回std::unique_ptr<A>
的朋友工厂函数,并使您的类没有可访问的构造函数。但是要使析构函数可用:
#include <memory>
class A;
template <class ...Args>
std::unique_ptr<A> make_A(Args&& ...args);
class A
{
public:
~A() = default;
private :
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
template <class ...Args>
friend std::unique_ptr<A> make_A(Args&& ...args)
{
return std::unique_ptr<A>(new A(std::forward<Args>(args)...));
}
};
现在您的客户端显然可以获得unique_ptr<A>
:
std::unique_ptr<A> p1 = make_A();
但是你的客户可以很容易地得到一个shared_ptr<A>
:
std::shared_ptr<A> p2 = make_A();
因为std::shared_ptr
可以由std::unique_ptr
构造。如果你有任何用户编写的智能指针,它们所要做的就是与你的系统互操作,创建一个带std::unique_ptr
的构造函数,就像std::shared_ptr
一样,这很容易做到:
template <class T>
class my_smart_ptr
{
T* ptr_;
public:
my_smart_ptr(std::unique_ptr<T> p)
: ptr_(p.release())
{
}
// ...
};
由于没有通用术语"智能指针",您想要的是不可能的。
你能做的,是支持一些已知的智能指针。通常的解决方案从您的开始,将tor或tor设为私有,并添加工厂函数。它可以返回包含所需智能指针的实例。如果您只想支持unique_ptr和shared_ptr,那就意味着两个工厂函数,不会太多。(请注意,这些指针允许通过简单的接口走私出原始指针,因此控件不是完整的。)