如何限制C++类的对象只能建立在堆上或栈上

C++中,类的对象建立分为两种,一种是静态建立,如A a; 另一种是动态建立,如 A *ptr = new A;

    静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。

    动态建立一个类对象,是使用new运算符将对象建立在堆空间中。这个过程分为两步:第一步,执行operator new()函数,在堆空间中搜索合适的内存并进行分配;第二步,调用构造函数构造对象,初始化这片内存空间;第三步,返回正确的指针。这种方法,间接调用类的构造函数。

 

一、只能建立在堆上

方法1:将类的析构函数设为private

方法2:将构造和析构函数设为protected,定义public static函数创建对象,定义public函数删除对象。[推荐使用]

    类对象只能建立在堆上,就是不能静态建立类对象,即不能直接调用类的构造函数。容易想到将构造函数设为私有。在构造函数私有之后,无法在类外部调用构造函数来构造类对象(即无法静态建立),只能使用new运算符来建立对象。C++提供new运算符的重载,但new函数只能用于分配内存,无法提供构造功能,因此这种方法不可行。[ 因为静态建立/动态建立一个类对象时,会直接/间接调用类的构造函数,所以将构造函数设为私有的方法不可行。]

    编译器管理了对象的整个生命周期,当对象建立在栈上时,由编译器分配内存空间,调用构造函数来构造栈对象。当对象使用完后,编译器调用析构函数来释放栈对象所占的空间。当编译器为类对象分配栈空间时,会先检查类的析构函数的访问性(不光是析构函数,只要是非静态的函数,编译器都会检查)。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。

class HeapOnly

{

public:

    HeapOnly(){}

    void destory(){delete this;}

private:

    ~HeapOnly(){}

};

 

int main()

{

    //HeapOnly objectHeapOnly;    // compile error

    HeapOnly *ptrHO = new HeapOnly;

    ptrHO->destory();

 

    return 0;

}

使用HeapOnly objectHeapOnly; 创建类对象时,编译阶段会报错。

$ g++ classObject.cpp

classObject.cpp: In function ‘int main()’:

classObject.cpp:7: error: ‘HeapOnly::~HeapOnly()’ is private

classObject.cpp:13: error: within this context

    上述代码代码有两个问题:

(1)无法解决继承问题。如果HeapOnly作为多态基类,则析构函数通常要设为virtual,然后在子类重写,以实现多态。因此析构函数不能设为private。

将析构函数设为protected可以有效解决这个问题,类外无法访问protected成员,子类可以访问。

(2)使用new创建一个类实例,却用destory函数释放对象,而不能使用delete删除对象。因为delete对象指针,会调用对象的析构函数,而析构函数在类外不可访问。

将构造函数设为protected,提供一个public的static函数来完成构造[静态成员函数可以通过类名直接访问](不使用new)。使用一个函数来构造,使用另一个函数来析构。

#include <iostream>

 

class HeapOnly

{

protected:

    HeapOnly(){}

    ~HeapOnly(){}

public:

    static HeapOnly* create()

    {

        return new HeapOnly();

    }

    void destory()

    {

        delete this;

    }

    void printLog()

    {

        std::cout<<"call printLog"<<std::endl;

    }

};

 

int main()

{

    HeapOnly *ptrHO = HeapOnly::create();

    ptrHO->printLog();

    ptrHO->destory();

 

    return 0;

}

 

二、只能建立在栈上

方法:将operator new()函数设为private

    只有使用new运算符,对象才能建立在堆上,因此禁用new运算符就可以实现类对象只建立在栈上。

class StackOnly

{

public:

    StackOnly(){}

    ~StackOnly(){}

private:

    void* operator new(size_t t){}

    void operator delete(void* ptr){}

};

 

 

参考:

http://blog.csdn.net/szchtx/article/details/12000867

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值