2013-05-03 76 views
4

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

我在想什么的是如下:

class Foo: 
#ifndef USE_BASIC 
public Advanced 
#else 
public Basic 
#endif 
{ 
... 
} 
在我的演示代码

并把#define USE_BASIC

#define USE_BASIC 
#include <Foo.h> 

但是富不从基本继承。我在这里做错了吗?或者如果有替代方案来解决这个问题?

+5

您必须在包含'Foo.h'的每个翻译单元(.cpp +包含的标题)中定义'USE_BASIC',在'#include '指令之前。考虑使用编译器开关(在每个翻译单元中自动声明“USE_BASIC”)或将#define定义在标题中。 – dyp 2013-05-03 12:24:39

+1

@Named我不同意。头文件没有特别之处,OP显示了在包含头文件之前定义'USE_BASIC'的例子。编译器在cpp上运行,因此预处理器首先看到_then_包含头部(在OP的例子中)。 – dyp 2013-05-03 12:29:05

+0

我无法理解-1。 – 2013-05-03 13:04:47

回答

14

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

下面是一个例子:

#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 
}; 

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

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

希望有所帮助。

+1

谢谢!知道这些方法是相当好的,虽然可能不适合我的情况,但不确定是否将模板添加到微处理器会使它更好或更邪恶...... – 2013-05-03 12:47:42

+0

@XunYang:你在说什么“微处理器”?你的意思是预处理器?如果是,那么你不需要使用带模板的预处理器。 – Nawaz 2013-05-03 12:51:01

+0

不是,它在Arduino上,所以这是一种嵌入式系统 – 2013-05-03 12:51:56

1

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

+0

如果内存有限或间接性能太差,这可能是不可能的。 – dyp 2013-05-03 12:30:58

2

这是库供应商不断面临的基本配置问题。对于小型项目,只需#defineUSE_BASIC,适当时在foo.h标题中。对于有大量配置选项的较大项目,您可能需要转到配置文件,该配置文件在每个库头中获取#include d并在那里定义适当的东西。在这种情况下,我会做所有选择的配置标题:

// uncomment to use `Basic` throughout: 
// #define USE_BASIC 
#ifdef USE_BASIC 
typedef Basic FooBase; 
#else 
typedef Advanced FooBase; 
#endif 
+1

我确定你的意思是'typedef Basic FooBase;'** not **'typedef FooBase Basic;'与其他typedef相同。 – Nawaz 2013-05-03 13:21:02

+0

@Nawaz - 哟,谢谢。不知道我是如何做出愚蠢的事情的。固定。 – 2013-05-03 15:05:55

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