C ++继承自已知基类的未知中间类

时间:2013-04-30 02:13:49

标签: c++ inheritance polymorphism

我有一个名为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,并且所有成员变量都会被偏移和破坏。 (我认为)

谢谢!抱歉,可以互换使用interface / abstract / pure虚拟。

3 个答案:

答案 0 :(得分: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

无论如何,they are just the same

答案 1 :(得分:1)

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

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

如果必须单独成为一个类,请考虑将其作为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();
  }
};

答案 2 :(得分: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”。