11

我正在研究一个微处理器(Arduino)项目。我的库Foo是从现有库继承的Basic。后来我将 , 的功能扩展Basic到另一个类Advanced。但是,Advanced这会使硬件更加难以扩展,使得其中一个已经制作的演示无法使用。

我正在考虑如下:

class Foo:
#ifndef USE_BASIC
public Advanced
#else
public Basic
#endif
{
...
}

并放入#define USE_BASIC我的演示代码:

#define USE_BASIC
#include <Foo.h>

但是 Foo 不是从 Basic 继承的。我在这里做错了吗?或者是否有其他方法可以解决这个问题?

4

4 回答 4

25

一个更干净的解决方案是使用 template :让编译器根据模板参数选择基类。

这是一个例子:

 #include <type_traits> //for std::conditional


 //here you go with your own class
 template<bool UseAdvanced>
 class Foo : public std::conditional<UseAdvanced, Advanced, Basic>::type
 {
      //your code
 };

以下是您将如何使用此类:

Foo<true>   fooWithAdvanced; //it uses Advanced as base class
Foo<false>  fooWithBasic;    //it uses Basic as base class!

好吧,这是一种方法。但是还有更好的方法。特别是,我将按以下方式设计类模板,其中模板参数将充当类。这将是更灵活的设计。

 template<typename Base>
 class Foo : public Base
 {
      //your code
 };

Basic因此,您可以使用Advanced任何其他类作为基类,只要它支持所需的功能Foo及其用法:

 Foo<Advanced>  fooWithAdvanced;
 Foo<Basic>     fooWithBasic;
 Foo<OtherBase> fooWithOtherBase;

希望有帮助。

于 2013-05-03T12:38:26.247 回答
2

这是库厂商经常面临的一个基本配置问题。对于小型项目,只需#define USE_BASIC在适当的时候在foo.h标题中添加 。对于具有大量配置选项的大型项目,您可能希望转到一个配置文件,该文件#include在每个库头中获取 d 并在那里定义适当的内容。在这种情况下,我会在配置标题中进行所有选择:

// uncomment to use `Basic` throughout:
// #define USE_BASIC
#ifdef USE_BASIC
typedef Basic FooBase;
#else
typedef Advanced FooBase;
#endif
于 2013-05-03T12:35:15.260 回答
1

另一种解决方案是避免继承并使用像Strategy这样提供更多灵活性的模式。因此,您可以将 Foo 在运行时的行为从 更改BasicAdvanced

于 2013-05-03T12:30:05.077 回答
1

有人提出了模式策略。如果您的选择是在编译时,您应该更好地使用基于策略的设计: http ://en.wikipedia.org/wiki/Policy-based_design

这与您的设计大致相同,但您使用模板:

template <class Base> class YourClass : public base {
    ...
};

使用时:

#ifdef BASIC
typedef YourFinalClass Yourclass<Basic>;
#else
typedef YourFinalClass Yourclass<Advanced>;
#endif
于 2013-05-03T12:35:16.443 回答