【问题标题】:C++: is conditional inheritance possibleC++:条件继承是可能的
【发布时间】:2023-03-28 19:32:01
【问题描述】:

我正在开发一个微处理器 (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 继承的。我在这里做错了吗?或者是否有其他方法可以解决这个问题?

【问题讨论】:

  • 您必须在包含Foo.h 的每个翻译单元(.cpp + 包含的标头)中,在#include &lt;Foo.h&gt; 指令之前定义USE_BASIC。考虑使用编译器开关(在每个翻译单元中自动声明 USE_BASIC)或将 #define 放在标题中。
  • @Named 我不同意。标头没什么特别的,OP 显示了在包含标头之前定义 USE_BASIC 的示例。编译器在 cpp 上运行,因此预处理器首先看到定义 然后 包括标题(在 OP 的示例中)。
  • 我看不懂-1。

标签: c++ inheritance arduino


【解决方案1】:

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

这是一个例子:

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

希望对您有所帮助。

【讨论】:

  • 谢谢!很高兴了解这些方法,但可能不适合我的情况,不确定将模板添加到微处理器中是好事还是坏事......
  • @XunYang:你在说什么“微处理器”?你是说预处理器吗?如果是,那么您不需要将预处理器与模板一起使用。
  • 不,它在 Arduino 上,所以这是一种嵌入式系统
  • @XunYang:我不认为模板会在 Arduino 中引起任何问题,因为一旦类模板被实例化,它就变得和任何其他普通类一样。
  • 模板不是 Arduino 编译器的默认语言功能,所以我需要引入另一个 3rd-part 库来使用模板,这将占用更多已经达到极限的存储空间。 . 不过可能值得一试,下一个项目:)
【解决方案2】:

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

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

【讨论】:

  • 我确定您的意思是 typedef Basic FooBase; 不是 typedef FooBase Basic; 与其他 typedef 相同。
  • @Nawaz - 是的,谢谢。不知道我是怎么做出这么傻的事的。固定。
【解决方案3】:

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

【讨论】:

  • 如果内存有限或间接影响性能太大,这可能是不可能的。
【解决方案4】:

有人提出了模式策略。 如果您的选择是在编译时,您应该更好地使用基于策略的设计: 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

【讨论】:

    猜你喜欢
    • 2019-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2011-11-14
    • 2012-02-24
    • 2015-04-19
    相关资源
    最近更新 更多