为什么在子类中没有正确定义#define?

时间:2016-02-04 20:17:28

标签: c++ c-preprocessor

我在基类头文件中有一个定义。无法在派生类中使用define:

Plugin.h

#ifndef PLUGIN_H
#define PLUGIN_H

#include "../config.h"

#ifdef DEBUG
#define DEBUG_PLUGIN(...) ets_printf( __VA_ARGS__ )
#else
#define DEBUG_PLUGIN(...)
#endif


class Plugin {
public:
  Plugin();
  ...

SimplePlugin.h

#ifndef SIMPLE_PLUGIN_H
#define SIMPLE_PLUGIN_H

#include "Plugin.h"

class SimplePlugin : public Plugin {
public:
  SimplePlugin();
  ...

SimplePlugin.cpp

#include "SimplePlugin.h"

SimplePlugin::SimplePlugin() : _devices() {
  DEBUG_PLUGIN("[SimplePlugin]\n");     // <-- not printed
}

config.h已定义DEBUG。你能突出预处理器魔术吗?

更新

这些评论让我走上正轨。宏扩展当然不依赖于类层次结构,实际上根本不在编译器上,而是在预处理器上。定义宏,由预处理器和执行器扩展,否则我们会看到编译错误。

最后证明Arduino / esp8266 ets_printf功能需要额外的硬件配置,否则它只会不可靠。这种不可靠的行为使它看起来好像只是根据文件/类层次结构中的位置调用它。

2 个答案:

答案 0 :(得分:3)

是的,你应该阅读更多关于C/C++ preprocessor的信息(C&amp; C ++共享相同的预处理器,预定义的宏中有some differences)。它仅以文本方式运行。它没有类型(例如class)或范围的概念。

您可以使用如下命令行获取SimplePlugin.cpp的预处理形式:

g++ -C -E SimplePlugin.cpp > SimplePlugin.ii

(您可能需要在-D之前添加一些额外的-I 符号-C 目录在编译命令中)

然后,使用您的编辑器或寻呼机查看生成的SimplePlugin.ii文件(来自SimplePlugin.cpp ...的预处理表单)。

您甚至可以使用

删除行信息(由#开头的行中的预处理器发出)
    g++ -C -E SimplePlugin.cpp | grep -v '^#' > SimplePlugin.nolines.ii

然后您可以运行g++ -c -Wall SimplePlugin.nolines.ii,诊断将引用预处理文件SimplePlugin.nolines.ii,而不是原始未经处理的SimplePlugin.cpp

另请阅读GNU cpp

的文档

(我猜你使用GCC;请调整我对你的编译器套件的答案;我甚至猜测你的bug可能与预处理无关)

答案 1 :(得分:1)

明显可能的解释是

  • ets_printf() - 这是非标准的,你没有描述 - 没有你认为的工作。例如,如果定义了DEBUG,它本身就是一个定义为什么都不做的宏。
  • DEBUG实际上并未在config.h中定义。某个地方的拼写错误很容易意味着正在定义其他宏,而不是你认为的宏。
  • 标题可能实际上是定义DEBUG,但预处理器随后遇到#undef DEBUG。这可能位于相同的标题,不同的标题中,甚至包含在源文件中。

问题不太可能与类或构造函数的定义有关。预处理器不遵循范围规则。

相关问题