如何定义一个只能在栈或者堆上生成的类
程序员文章站
2022-07-02 14:29:43
...
如何定义一个只能在栈上或者堆上生成的类呢?
这主要考察的是对C++语法和内存管理的掌握,在C++中的内存是如何管理的呢?下面是我自己理解的一张内存管理的图:
一.定义一个只能在堆上生成的类
分析:我们都知道一个对象是既可以在栈上生成也可以在堆上new出来,要想生成一个只能在堆上生成的类,也就是说,局部对象,静态对象,全局对象都不能生成,那么我们可以将构造函数写成私有或者保护(类外不可以直接访问的),通过new来构造出一个堆上的对象;
可以在类内new一个对象并提供一个公有的接口来返回这个对象。接下来如果在类外定义类对象的话,只需要调用这个函数即可。貌似这样做还是行不通,因为在类外只能由类对象调用类成员函数,C++是十分强大的,它提供了静态成员函数,所谓的静态成员函数它是没有隐含this指针参数,所以可以使用类型::作用域访问符直接调用静态成员函数,这样问题就解决啦!!!
实现代码如下:
class Base
{
protected: //私有或者保护构造函数
Base(int d=0)
:_d(d)
{
cout<<"Base()"<<endl;
}
~Base()
{
cout<<"~Base()"<<endl;
}
public:
//提供静态的成员方法获得当前对象
static Base *GetOBJ(const int& d)
{
cout<<"GetOBJ()"<<endl;
return new Base(d);
}
static void Delete(Base *b) //可以声明为静态的也可以声明为非静态的
{
cout<<"Delete()"<<endl;
delete b;
}
private:
int _d;
};
void Test()
{
//Base tmp; //error
Base *b=Base::GetOBJ(5);
Base::Delete(b);
}
二.定义一个只能在栈上生成的类
想法一:要想只在栈上定义对象,就不能使用new,也不能定义全局和静态变量,我们可以通过以下的方式实现:将构造函数设为私有或者保护,然后写一个公有方法去获取对象,但是不能使用new这个操作符。
代码如下:
class Base
{
public:
static Base GetObject(int b) //此处不能返回引用
{
return Base(b);
}
int GetData()
{
return _b;
}
private:
Base(int b=0)
:_b(b)
{}
private:
int _b;
};
void Test()
{
//Base *tmp=new Base(); //error
Base b = Base::GetObject(5);
cout<<b.GetData()<<endl;
}
但是这种想法存在一个弊端就是:依然无法摆脱定义定义静态变量和全局变量。。。
想法二:只能在栈上开辟对象,也就是说不能在堆上开辟了。产生堆对象的唯一方法就是使用new,而禁止使用new也就是不能在堆上产生对象了。由于new执行时会调用operator new, 而operator new是可重载的, 所以将operator new和operator delete重载为私有即可。
实现代码如下:
class Base
{
public:
Base(int b=0)
:_b(b)
{}
~Base()
{
cout<<"~Base()"<<endl;
}
private:
void *operator new(size_t size); //对new和delete进行私有处理
void operator delete(void *ptr);
private:
int _b;
};
void Test()
{
Base b(10);
//Base *tmp=new Base(); //error虽然此时构造函数是共有的,但是new这个操作符却是私有的
}
在这里就分享结束了~~~
推荐阅读