C/C++ define IDisposable Interface

C/C++ 定义 “IDisposable”,用于管理被实例化的对象持有资源的释放是有必要的一种设计模式,很多人习惯使用析构来释放,但这只适用于不涉及虚函数的情况。

C/C++ 结构/类型析构函数及构造函数不可以调用虚函数,在不同的编译器上有不同的表现,如函数被定义虚函数且为抽象(Abstract)那么析构函数内调用会崩溃,C# 语言没有真正意义上与C/C++相同的析构函数,在C#语言中析构函数可以调用虚函数,这是因为.NET虚拟机在调用析构函数时采用的办法是类似用户调用 “Dispose()” 虚函数(il.callvirt)的行为,此时并没有释放引用对象上面的虚表指针,而在 C/C++ 中析构会破坏当前的虚表指针,所以C/C++析构函数内无法连接到虚函数,但并非绝对的,GCC/VC++ 编译器允许析构内连接虚函数,但仅限于当前结构/类型的成员函数,而重载虚表的虚函数不能被调用。

C/C++ 应用程序一个好的设计及编码,应该避免过度依赖析构函数释放资源,这容易引发一些不必要的内存安全问题。

所有的对象持有的托管/非托管资源及内存都应该由对象派生接口 “IDisposable” 的 “Dispose()” 具现函数处理,C/C++ 析构函数仅用于 STL/Boost 类型成员编译器自行析构或逃逸的非托管资源释放。

注意:

托管资源一般泛指由对象本身持有管理的数据,它可以是其它对象的共享/唯一引用,简单理解,可以是认为 std::shared_ptr、boost::shared_ptr 指向的类型对象实例,非托管资源,可以理解为 “操作系统句柄”、“硬件物理/虚拟内存资源”。

应用代码:

    std::shared_ptr<User> user = Reference::NewReference<User>();
    uusing(user);

实现代码:

class Reference : public std::enable_shared_from_this<Reference> {
public:
    inline Reference() noexcept
        : enable_shared_from_this() {

    }

public:
    inline std::shared_ptr<Reference>               GetReference() const noexcept {
        return const_cast<Reference*>(this)->shared_from_this();
    }

public:
    template<typename _Ty1, typename _Ty2>
    inline static std::shared_ptr<_Ty1>             AsReference(const std::shared_ptr<_Ty2>& v) noexcept {
        return v ? std::dynamic_pointer_cast<_Ty1>(v) : NULL;
    }

public:
    template<typename _Ty1, typename _Ty2>
    inline static std::shared_ptr<_Ty1>             CastReference(const std::shared_ptr<_Ty2>& v) noexcept {
        if (!v) {
            return NULL;
        }

        _Ty2* native_pTy2 = const_cast<_Ty2*>(v.get());
        _Ty1* native_pTy1 = static_cast<_Ty1*>(native_pTy2);

        const std::shared_ptr<_Ty2> shared_pTy2 = v;
        return std::shared_ptr<_Ty1>(native_pTy1, [shared_pTy2](const void*) noexcept {});
    }

public:
    template<class _Ty1 = Reference, class _Ty2 = Reference, typename... A>
    inline static std::shared_ptr<_Ty1>             NewReference2(A&&... args) noexcept {
        static_assert(sizeof(_Ty1) > 0 && sizeof(_Ty2) > 0, "can't make pointer to incomplete type");

        _Ty2* p = (_Ty2*)Malloc(sizeof(_Ty2));
        return std::shared_ptr<_Ty1>(new (p) _Ty2(std::forward<A&&>(args)...),
            [](_Ty2* p) noexcept {
                p->~_Ty2();
                Mfree(p);
            });
    }

    template<class _Ty1 = Reference, typename... A>
    inline static std::shared_ptr<_Ty1>             NewReference(A&&... args) noexcept {
        return NewReference2<_Ty1, _Ty1>(std::forward<A&&>(args)...);
    }
};

class IDisposable : public Reference {
public:
    virtual void                                    Dispose() = 0;
};

class User : public IDisposable {
    virtual void                                    Dispose() override {};
};

void uusing(const IDisposable* disposable) {
    if (disposable) {
        const_cast<IDisposable*>(disposable)->Dispose();
    }
};

template<typename Reference>
void uusing(const std::shared_ptr<Reference>& reference) {
    if (reference) {
        uusing(reference.get());
    }
}

template<typename Reference>
void uusing(const std::unique_ptr<Reference>& reference) {
    if (reference) {
        uusing(reference.get());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值