【问题标题】:Why is #define not properly defined in child classes?为什么在子类中没有正确定义#define?
【发布时间】:2016-02-04 20:17:27
【问题描述】:

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

插件.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。你能强调一下预处理器的魔力吗?

更新

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

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

【问题讨论】:

  • 你确定ets_printf函数能正常工作吗?
  • 你真的创建了 SimplePlugin 的实例吗?
  • 宏的行为与类和派生无关。但是,您的头文件包含结构看起来不错,这意味着该宏很可能按应有的方式工作和工作。如果在您的情况下“未打印”某些内容,则不应归咎于预处理器和宏。
  • 如果没有定义 amacro,你会得到编译错误,不会丢失运行可执行文件的输出。
  • 问题可能出在config.h 的某个地方,因为问题似乎是在编译器到达DEBUG_PLUGINPlugin.h 中的定义时还没有定义DEBUG。我在 TutorialsPoint 的在线编译器中使用与您的问题相同的文件设置对其进行了测试,并且它有效。 (请参阅 goo.gl/a8MtrF ,尽管您可能需要先 g++ main.cpp SimplePlugin.cpp 才能运行 a.out。)

标签: c++ c-preprocessor


【解决方案1】:

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

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

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

(您可能必须在 -C 之前添加一些额外的 -Dsymbol-I目录,就像在编译命令中一样)

然后,使用编辑器或寻呼机查看生成的 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;请根据您的编译器套件调整我的答案;我什至猜您的错误可能与预处理无关)

【讨论】:

  • C 和 C++ 预处理器有很多共同点,但实际上并不完全相同。有很多讨论,例如stackoverflow.com/questions/5085533/…
  • @Peter:谢谢,改进了我的回答。
  • 好的答案,但不是根本原因。
【解决方案2】:

明显的可能解释是

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多