设计一个禁止在堆中实例化的类,需要重载operator new和operator delete,并将其设为private。当然,也不是没有破解的方法,那就是placement new。
// 禁止在堆中实例化对象?
// 在堆中实例化对象,需要使用new和delete,因此如果想要禁止,那就重载...
// (1)禁止用户在堆中实例化对象:将new和delete重载为私有或保护函数
// (2)连类内部的成员函数都不能用new和delete:重载new和delete为私有成员函数,但是只声明,不实现
#include <iostream>
#include <new>
using namespace std;
// A:用户不能用new,自己可以用new
class A
{
public:
A(){cout<<"A:: ctor"<<endl;}
~A(){cout<<"~A::decon"<<endl;}
static void use_new()
{
A*p=new A;
cout<<"use_new"<<endl;
delete p;
p=0;
}
void print(){cout<<"It is A"<<endl;}
private:
void *operator new(size_t){}
void operator delete(void *p){}
};
// B:用户不能用new,自己也不可以用new
class B
{
public:
B(){cout<<"B:: ctor"<<endl;}
~B(){cout<<"~B::decon"<<endl;}
void print(){cout<<"It is B"<<endl;}
static void use_new() // 这个函数永远不可使用!除非实现operator new和operator delete
{
B*p=new B;
cout<<"use_new"<<endl;
delete p;
p=0;
}
private:
void *operator new(size_t);
void operator delete(void *p);
};
int main()
{
{
A a;
B b;
A::use_new(); // use_new成员函数使用了new/delete,类A可以在成员函数中使用new和delete
// B::use_new(); // 如果去掉注释,在链接时会报错
}
cout<<endl<<endl;
{
cout<<"0 ";
char *cp = new char [sizeof(A)];
cout<<"1 ";
A *ap=::new((void*)cp) A; // placement new! 用(::new),否则系统会首先调用重载的那个new.
// placement new绕过了operator new,可以在任意位置调用构造函数...!
cout<<"2 ";
ap->print();
cout<<"3 ";
ap->~A(); // 显式调用析构函数别忘记。
cout<<"4 ";
delete cp;
cout<<endl;
}
return 0;
}
run:
chen@chen-book1:~$ g++ stackonly.cpp -o stackonly
chen@chen-book1:~$ ./stackonly
A:: ctor
B:: ctor
A:: ctor
use_new
~A::decon
~B::decon
~A::decon
0 1 A:: ctor
2 It is A
3 ~A::decon
4
chen@chen-book1:~$