C ++:条件继承是可能的

时间:2013-05-03 12:20:35

标签: c++ inheritance arduino

我正在开发一个微处理器(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 个答案:

答案 0 :(得分:16)

更简洁的解决方案是使用模板:让编译器根据模板参数选择基类。

以下是一个例子:

 #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!

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

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

所以你可以使用BasicAdvanced任何其他类作为基类,只要它支持Foo及其所需的功能。用法:

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

希望有所帮助。

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

答案 2 :(得分:1)

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

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