C++类实现只能静态和动态分配

C++类如何实现只能静态分配和只能动态分配

只能动态分配(只能通过 new创建在堆上)
核心思想:将析构函数设为 protected或 private。
为什么?
栈对象(静态分配)在离开作用域时,编译器会自动调用析构函数。如果析构函数不可访问,编译器会报错,从而阻止其在栈上创建。
new操作符分为两步:1. 分配内存 (operator new) 2. 调用构造函数。它并不在创建时检查析构函数的访问权限。
delete操作符会调用析构函数,因此我们必须提供一个公有的销毁方法来执行 delete this,这个方法必须是类的成员函数或友元

class DynamicOnly {
public:
    // 1. 公有构造函数
    DynamicOnly() {
        std::cout << "DynamicOnly constructor\n";
    }

    // 2. 提供公有的销毁方法,代替析构函数
    void destroy() {
        delete this; // 在类内部,可以调用私有析构函数
    }

    // 3. 可选:提供一个静态的创建方法,更规范
    static DynamicOnly* create() {
        return new DynamicOnly();
    }

protected:
    // 4. 关键:将析构函数设为protected或private
    ~DynamicOnly() {
        std::cout << "DynamicOnly destructor\n";
    }
};

// 使用方式
int main() {
    // DynamicOnly obj1; // 错误:析构函数不可访问,无法在栈上创建
    // DynamicOnly* obj2 = new DynamicOnly(); 
    // delete obj2;      // 错误:析构函数不可访问,无法直接delete

    DynamicOnly* obj = DynamicOnly::create(); // 正确:在堆上创建
    obj->destroy();                           // 正确:通过公有方法销毁
    // 或者: obj->destroy();
}

只能静态分配(只能在栈上创建)
核心思想:将 operator new和 operator delete重载为 private或使用 = delete。
为什么?
使用 new表达式创建对象时,会先调用 operator new分配内存,再调用构造函数。
如果 operator new是不可访问的,new表达式就会编译失败,从而阻止其在堆上创建。
析构函数必须是公有的,以便栈对象离开作用域时能正常被调用。

class StaticOnly {
public:
    StaticOnly() {
        std::cout << "StaticOnly constructor\n";
    }
    ~StaticOnly() { // 公有析构函数
        std::cout << "StaticOnly destructor\n";
    }

private:
    // 1. 将operator new设为私有,阻止new表达式
    void* operator new(size_t size) {
        return ::operator new(size);
    }
    void* operator new[](size_t size) {
        return ::operator new[](size);
    }

    // 2. 同样需要禁止placement new(可选但推荐)
    void* operator new(size_t, void* ptr) = delete;
    void* operator new[](size_t, void* ptr) = delete;

    // 3. 对应的operator delete也设为私有
    void operator delete(void* ptr) {
        ::operator delete(ptr);
    }
    void operator delete[](void* ptr) {
        ::operator delete[](ptr);
    }
};

// 使用方式
int main() {
    StaticOnly obj;          // 正确:在栈上创建
    // StaticOnly* p = new StaticOnly(); // 错误:operator new是私有的
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值