gpt4 book ai didi

c++ - 创建对象时使用类关系进行适当封装

转载 作者:搜寻专家 更新时间:2023-10-31 01:34:15 24 4
gpt4 key购买 nike

我正在编写一个基于 libusb 的 C++ 包装器练习。我希望我的 API 完全隐藏底层库的实现:用户甚至不应该知道我实际上在使用 libusb。所以我创建了两个类:ContextDeviceDevice 是使用 open 方法从 Context 创建的。

所以:

//--- context.hpp -------------------
class Context final
{
public:
Context();
~Context();

std::unique_ptr<Device> open(uint16_t vid, uint16_t pid);

private:
struct Impl;
std::unique_ptr<Impl> impl;
};

//--- context.cpp -------------------
struct Context::Impl
{
libusb_context* ctx;
};

Context::Context()
: impl(std::make_unique<Impl>())
{ /* ... */ }

//--- device.hpp -------------------
class Device final
{
public:
Device();
~Device();

private:
struct Impl;
std::unique_ptr<Impl> _impl;
};

//--- device.cpp -------------------
struct Device::Impl
{
libusb_device_handle* handle;
}

Device::Device()
: _impl(std::make_unique<Impl>())
{}

现在的问题是:如何实现open方法?我需要在实现中调用 libusb_open_device_with_vid_pid,它将获取我的 Context::Impllibusb_context* 并将句柄存储在 Device 中::实现。以下是我认为的选项:

  1. 我创建了一个 Device 的构造函数,它接受一个指向 Context 的指针,但是 Device 的构造函数没有访问 的权限libusb_context* 调用函数的指针;
  2. 我遵循第一点并将 Context::Impl 放在 header 中,并使 Device 成为 Context 的 friend :这听起来很丑虽然;
  3. 我创建了一个 Device 的构造函数,它接受一个 libusb_context* 指针:但是我会破坏封装,用户不应该看到 libusb 的细节;
  4. 我向 Context 添加了一个 native_handle 方法,这样我就可以做第一个并获得实现指针,但会导致与第三个相同的问题。
  5. 我在 open 中进行了函数调用,但是如何使用我得到的 libusb_device_handle* 初始化我的 Device?我不能让 Device 的构造函数采用这样的指针,破坏封装。

最佳答案

friend基于的解决方案实际上是最干净的,这就是friend专为。

// device.hpp
class Device final
{
public:
~Device();

private:
Device();
struct Impl;
std::unique_ptr<Impl> impl;
friend class Context;
};

// device.cpp
struct Device::Impl
{
libusb_device_handle* handle;
Impl() : handle(nullptr) {}
}

Device::Device() : impl(new Device::Impl()) {}

std::unique_ptr<Device> Context::open(uint16_t vid, uint16_t pid) {
std::unique_ptr<Device> result(new Device());
result->impl->handle = libusb_open_device_with_vid_pid(vid, pid);
return result;
}

请注意,您实际上可以返回 Device而不是 std::unique_ptr<Device>并将所有绑定(bind)视为值对象以避免额外的间接级别。

编辑:另一种选择是使用空指针。这会以引入潜在不安全的强制转换为代价删除友元声明。

// device.hpp
class Device final
{
public:
~Device();

private:
Device(void *handle);
struct Impl;
std::unique_ptr<Impl> impl;
};

// device.cpp
struct Device::Impl
{
libusb_device_handle* handle;
Impl(void *handle)
: handle(static_cast<libusb_device_handle*>(handle)) {}
}

Device::Device(void *handle)
: impl(new Device::Impl(handle)) {}

std::unique_ptr<Device> Context::open(uint16_t vid, uint16_t pid) {
void *handle = libusb_open_device_with_vid_pid(vid, pid);
std::unique_ptr<Device> result(new Device(handle));
return result;
}

关于c++ - 创建对象时使用类关系进行适当封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39927281/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com