2013-05-03 41 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