目前尚不清楚您要达到的目标。但是你已经被问到了,并且没有很清楚地澄清它。在您的回答评论中,您写道“我的意思不仅是 [禁止] 实例化,还包括对类的任何类型的引用(例如将其用作函数中的参数类型)”。
从表面上看,这意味着在你的头文件中使用以下内容:
struct BlahImpl;
typedef boost::shared_ptr<BlahImpl> Blah;
// Functions that create or give access to Blah instances.
然后客户端代码可以创建或访问Blah 实例,并复制它们(使用隐含的共享语义),但实际上不对它们做任何事情。充其量它们可以作为证明某些函数已被较早调用(产生一个实例)的证据。或者也许某些东西是由涉及此类实例的函数调用模式控制的,但无论如何,boost::shared_ptr 将完全不相关和多余。
因此,也许您的意思并不是您写的确切内容,而是类似“任何BlahImpl 实例应由boost::shared_ptr 动态分配和封装”。
如果是这样,您可以通过以下方式实现:
例子:
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <stddef.h> // ptrdiff_t, size_t
#include <string>
using namespace std;
namespace cpp11 {
using boost::shared_ptr;
};
template< class Type >
void destroy( Type const* p ) { delete p; }
class OnlySharedPtrUsage
{
public:
virtual ~OnlySharedPtrUsage() {}
struct InstantiationObfuscation;
static void* operator new( size_t size, InstantiationObfuscation* )
{
return ::operator new( size );
}
static void operator delete( void* p, InstantiationObfuscation* )
{
::operator delete( p );
}
static void operator delete( void* p )
{
::operator delete( p );
}
};
#define NEW_SHARED( type, args ) \
::cpp11::shared_ptr<type>( \
new( (type::InstantiationObfuscation*)0 ) type args, \
destroy<type> \
)
class MyClass
: public OnlySharedPtrUsage // The NEW_SHARED macro simplies.
{
template< class Type > friend void destroy( Type const* );
private:
string helloText_;
MyClass( MyClass const& ); // No such.
MyClass& operator=( MyClass const& ); // No such.
protected:
virtual ~MyClass() // Only dynamic allocation allowed.
{
cout << "MyClass::<destroy>()" << endl;
}
public:
string helloText() const { return helloText_; }
MyClass( string const& text )
: helloText_( text )
{
cout << "MyClass::<init>( string )" << endl;
}
};
int main()
{
// MyClass o( "a" ); // ! Does not compile, not dynamic.
// MyClass* p = new MyClass( "b" ); // ! Does not compile, not "mangled".
cpp11::shared_ptr< MyClass > sp = NEW_SHARED( MyClass,( "Hello from MyClass!" ) );
cout << sp->helloText() << endl;
}
注意这个例子不直接支持make_shared的优化。混淆分配器功能(正式的放置功能)与make_shared 不太匹配。但我想可以通过定义一个分配器类并使用alloc_shared来完成。
另外请注意,这种方法仅支持标头模块;无需单独编译。 :-)
哦,对于一般情况,您还需要为数组添加分配器函数。