首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++句柄类抽象

C++句柄类抽象
EN

Stack Overflow用户
提问于 2021-06-11 22:40:57
回答 2查看 164关注 0票数 0

我试图通过类的使用来抽象原始句柄的显式创建和销毁。实际句柄存储为私有类成员(这样用户就不会与较低级别的详细信息交互),它是在构建时创建并在销毁时销毁的。是否有某种类型的设计模式可以帮助实现下面代码试图实现的目标?

请注意,有可能存在大量相互依赖的类,因此使用大量的朋友语句污染每个类既乏味又糟糕。

代码语言:javascript
复制
#include <memory>

// Handle types may vary
typedef uint32_t A_Handle;
typedef uint32_t B_Handle;
typedef int64_t C_Handle;

extern void createA(A_Handle*);
extern void destroyA(A_Handle);
extern void createB(B_Handle*);
extern void destroyB(B_Handle);
extern void createC(C_Handle*, A_Handle, B_Handle);
extern void destroyC(C_Handle, A_Handle, B_Handle);

class A
{
private:
    A_Handle handle_;
public:
    A()
    {
        createA(&handle_);
    }

    ~A()
    {
        destroyA(handle_);
    }

    A(const A&) = delete;

    A& operator=(const A&) = delete;
};

class B
{
private:
    B_Handle handle_;
public:
    B()
    {
        createB(&handle_);
    }

    ~B()
    {
        destroyB(handle_);
    }

    B(const B&) = delete;

    B& operator=(const B&) = delete;
};

class C
{
private:
    C_Handle handle_;
public:
    std::shared_ptr<A> a;
    std::shared_ptr<B> b;

    C(const std::shared_ptr<A>& a, const std::shared_ptr<B>& b)
        : a(a)
        , b(b)
    {
        // Error a->handle_ and b->handle_ is private
        createC(&handle_, a->handle_, b->handle_);
    }

    ~C()
    {
        // Error a->handle_ and b->handle_ is private
        destroyC(handle_, a->handle_, b->handle_);
    }

    C(const C&) = delete;

    C& operator=(const C&) = delete;
};

// ...

int main()
{
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();
    std::shared_ptr<C> c = std::make_shared<C>(a, b);

    // ...

    return EXIT_SUCCESS;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-11 23:06:21

是否有某种类型的设计模式可以帮助实现下面代码试图实现的目标?

是。它被称为资源获取( Resource )初始化,简称RAII。你的第一次尝试是朝着正确的方向,但很可能是不完整的。需要关注的是,通常多次“销毁”原始句柄是一个错误。因此,您应该建立一个“类不变”,作为每个成员函数的post条件,类的两个实例都没有相同的原始句柄。您的类当前违反了这样的不变条件。考虑当您复制一个实例时会发生什么。有一条经验法则叫做五法则(以前是三条规则),这将有助于建立这个不变式。

至于私人访问和避开朋友,一个很好的解决方案是提供一个公共获取者:

代码语言:javascript
复制
class A
{
public
    A_Handle get_handle() { return handle; }

成员仍然被封装,类的用户将无法打破不变量,因为他们不能修改它。

票数 1
EN

Stack Overflow用户

发布于 2021-06-11 23:20:45

你不需要自己解决这个问题。相反,您可以将std::unique_ptr与自定义删除器一起使用,后者知道如何在unique_ptr超出作用域时销毁句柄。

下面是一个示例,使用FILE *作为“句柄”:

代码语言:javascript
复制
#include <cstdio>
#include <memory>

int main ()
{
    FILE *f = std::fopen ("myfile", "r");
    if (f)
    {
        std::unique_ptr <FILE, decltype (&std::fclose)> upf (f, std::fclose);
        // do things with the open file
        // ...
        // file will be closed here, when upf goes out of scope
    }
}

如果句柄不是指针类型,则可以将其转换为void * (大多数句柄都适合于void *) )。例如:

代码语言:javascript
复制
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdint>
#include <memory>

int main ()
{
    int fd = open ("myfile", O_RDONLY);
    if (fd >= 0)
    {
        std::unique_ptr <void, void (*) (void *)> upfd
            ((void *) (uintptr_t) fd, [] (void *fd) { close ((int) (uintptr_t) fd); });
        // do things with the open file
        // ...
        // file will be closed here, when upfd goes out of scope
    }
}

当然,您可以为那些看起来复杂的模板定义类型别名,以使代码更加整洁。

std::unique_ptr有一些很好的特性,包括一个删除的复制构造函数和一个可行的移动构造函数。此外,如果需要共享所有权语义(也称为引用计数),您也可以在std::shared_ptr中使用类似的技巧。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67944163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档