1

我有一个抽象类,称为 UsbDevice(主要是纯虚拟的)。它做的不多,但三个派生类做了:

class WindowsUsbDevice : public UsbDevice
class LinuxUsbDevice : public UsbDevice
class OsxUsbDevice : public UsbDevice

这些类中的每一个都没有真正添加任何公共方法——相反,它们只是 UsbDevice 抽象类的不同实现。

现在,我想创建一个派生自这些类中的任何一个的新类,我们称之为 FancyUsbDevice。可以说它代表一个特定的设备。

这个新类需要公开完整的 UsbDevice 接口(由中间类实现),以及公开一些只使用 UsbDevice 接口上的方法的花哨的高级函数——不需要公开任何特定于这些中间类之一的东西.

我可以看到三种可能的选择,我想知道它们是否可行,以及哪一种是最好的。

A) 不要继承,而是让 FancyUsbDevice HAS-A UsbDevice* 而不是 IS-A。(回避问题。我不喜欢这个选项,但感觉很安全。)

B)假设我有一个罕见的优势,即只有其中一个类实际上构建在任何特定平台上,#ifdef 继承字符串:(再次回避问题)

#ifdef WIN32
class FancyUsbDevice : public WindowsUsbDevice
#endif
#ifdef LINUX
class FancyUsbDevice : public LinuxUsbDevice
#endif

...

C) 模板!从模板类型继承:

Template<typename T> class FancyUsbDevice : public T

将其构造为子类型,并将其转换为接口:

FancyUsbDevice<WindowsUsbDevice> fancy_device;
FancyUsbDevice<UsbDevice> generic_fancy_device = dynamic_cast<FancyUsbDevice<UsbDevice>>(fancy_device);

但是,我认为这行不通,至少因为编译器会认为 generic_fancy_device 小于 fancy_device,并且所有成员变量都会被偏移和破坏。(我认为)

谢谢!很抱歉互换使用接口/抽象/纯虚拟。

4

3 回答 3

2

为什么不只是

#ifdef WIN32
typedef WindowsUsbDevice FancyUsbDevice;
#endif

#ifdef LINUX
typedef LinuxUsbDevice FancyUsbDevice;
#endif

或者如果你想用 C++11 的方式来做

#ifdef WIN32
using FancyUsbDevice = WindowsUsbDevice;
#endif

#ifdef LINUX
using FancyUsbDevice = LinuxUsbDevice;
#endif

无论如何,它们都是一样的

于 2013-04-30T02:23:49.610 回答
1

因此,如果我理解正确,您希望有一个类 a) 以UsbDevice与特定于操作系统的实现相同的方式实现接口,并且 b) 添加更多基于该接口的功能。

最简单的事情是不要创建另一个类,而只是将附加功能作为一组函数提供,并将 aUsbDevice作为参数。毕竟,您并没有真正添加功能,您只是将现有功能组合到新功能中。如果您没有创建大量的辅助函数,那可能是正确的做法。

如果它必须是一个单独的类,请考虑将其作为UsbDevice. 我想您有一些工厂方法,可以根据您所在的操作系统为您提供正确的实现。装饰器看起来像这样:

class UsbMoreFuncDecorator: UsbDevice {
  std::unique_ptr<UsbDevice> deviceImpl;
public:

  UsbMoreFuncDecorator(Param param) 
    : deviceImpl(UsbDeviceFactory.create(param))  
  //  ^-- Win or OsX or Linux - doesn't matter
  {}

  // delegate the UsbDevice virtual functions to the actual implementation
  virtual void someBasicUsbDeviceFunc() final {
    deviceImpl->someBasicUsbDeviceFunc();
  }

  // use the UsbDevice functions to compose more functionality
  void someMoreFunctionality() {
    someBasicUsbDeviceFunc();
    someOtherUsbDeviceFunc();
  }
};
于 2013-04-30T11:28:09.933 回答
0

选项 B 将以最少的麻烦完全按照您的意愿行事。在这一点上,与其使用 ifdef,不如在其他地方说:

#ifdef WIN32
    typedef WindowsUsbDevice NativeUsbDevice
    // any other such typedefs needed for Windows
#endif  // and similarly for Linux and OSX

然后

class FancyUsbDevice : public NativeUsbDevice

如果您使用的是 C++11,则可以使用“using”而不是“typedef”。

于 2013-04-30T02:22:53.103 回答