【问题标题】:How to override "default" #define values ​of a C ++ library header with new values ​defined in an application header如何用应用程序头中定义的新值覆盖 C++ 库头的“默认”#define 值
【发布时间】:2020-06-23 19:54:46
【问题描述】:

我要做的是为库提供一些由库头中的#define 指令设置的默认值。这些将确定库代码的哪些功能将使用给定的应用程序进行编译。如果应用程序开发人员需要添加或删除库函数,它应该用新值“覆盖”库的默认值而不修改库。除了修改库编译代码之外,这些应用程序头的#define 值将依次添加或删除应用程序代码本身的部分。这适用于嵌入式系统,因此即使节省少量内存也很重要。

以下是 4 个测试文件。如果甚至可以做到这一点,我就无法让它工作。也许正确的问题是:项目文件中#define / #undef 的正确顺序是什么?

library.h:

#ifndef MY_LIBRARY_H
#define MY_LIBRARY_H

#include <stdio.h>

#define FUNCTION_1 true
#define FUNCTION_2 false

class Class {
   public:
    Class();
    ~Class();
#if FUNCTION_1
    void Function_1(void);
#endif
#if FUNCTION_2
    void Function_2(void);
#endif
};

#endif  // MY_LIBRARY_H

library.cpp:

#include "library.h"

Class::Class() { /* Constructor */ };
Class::~Class() { /* Destructor */ };

#if FUNCTION_1
void Class::Function_1(void) {
    printf("Hi, this is %s running ...\n\r", __func__);
}
#endif

#if FUNCTION_2
void Class::Function_2(void) {
    printf("Hi, this is %s running ...\n\r", __func__);
}
#endif

tst-09.h

#ifndef TST_09_H
#define TST_09_H

#include <library.h>

#undef FUNCTION_2        // .....................................................
#define FUNCTION_2 true  // THIS IS WHERE I'M TRYING TO OVERRIDE THE LIB DEFAULTS

#endif  // TST_09_H

tst-09.cpp:

#include "tst-09.h"

int main(void) {
    Class object;
#if FUNCTION_1
    object.Function_1();
#endif
#if FUNCTION_2
    object.Function_2();
#endif
}

【问题讨论】:

  • #define _LIBRARY_H_ 该标识符保留给语言实现。您应该为标头保护宏使用另一个名称。
  • 不要违背库的意愿覆盖它。让它与选定的宏合作,那些你想要默认定义但可以覆盖的宏。
  • 尽量不要使用宏,除非你真的,真的别无选择。
  • 任何以下划线开头后跟大写字母的宏名称都是保留的。而不是_LIBRARY_H__MY_LIBRARY_H_ 使用简单的MY_LIBRARY(带或不带下划线)。
  • 感谢您的建议,我将更改示例代码。

标签: c++ preprocessor-directive


【解决方案1】:

利用链接器的功能。如果您想从二进制文件中排除未使用或不必要的代码,一种方法是将每个函数放在其自己的源模块中。 (一些编译器包支持函数级链接,链接器可以删除未引用的函数。)

尝试以您在问题中显示的方式使用宏需要在命令行上定义它们(并且库会在任何更改后重新构建)。

【讨论】:

  • 一点上下文:该库是为 Arduino 开发人员准备的。它与远程设备的功能相匹配。我可以为它提供所有启用的功能,但这将是一种浪费。由于是 Arduino,包含/排除代码的解决方案必须易于掌握。开发人员通常从 IDE 获取“Internet”库并直接使用它们。在某些情况下,他们甚至不知道文件保存在哪里,因此调整链接器标志不是一种选择。无论如何,我知道使用宏不是一个可能的解决方案。一个主要限制是它必须从“草图”代码或 IDE 内部解决。
猜你喜欢
  • 2017-06-28
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多