欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何定义一个只能在栈或者堆上生成的类

程序员文章站 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这个操作符却是私有的
}

在这里就分享结束了~~~