c++ - 头球后卫似乎不起作用?

标签 c++ header-files

我在单独的头文件中声明了一些常量变量(即 constant.h)。

我在我的 debug.cpp 中包含 constant.h 以访问变量。

我在我的 ma​​in.cpp 中包含了 constant.hdebug.h 以访问变量。

当我编译时,它显示的错误是 **multiple definition** of **IF_DEBUG_ENABLED**

请告诉我实际上我做错了什么。另外,请注意,这是我的第一天第一个 c/c++ 应用程序。我什至从未在学校读过它。

我的代码源如下: 作为

/-- constant.h --/

#ifndef CONSTANT_H
#define CONSTANT_H

const char* APP_NAME            = "ymcmcb";
const bool  IF_DEBUG_ENABLED    = true;

#endif // CONSTANT_H

/--调试.h--/

#ifndef DEBUG_H
#define DEBUG_H

#include <QString>

class Debug
{  
public:
    static void Log(QString Message);
};

#endif // DEBUG_H

/--调试.cpp--/

#include "constant.h"
#include "debug.h"

#include "QDebug"

static void Log(QString Message)
{
    if (IF_DEBUG_ENABLED)
        qDebug() << Message;    //It says problem is here
}

/-- main.cpp --/

#include "constant.h"
#include "debug.h"

int main(int argc, char *argv[])
{
    Debug::Log("New application has been run");
}

最佳答案

C和C++有“编译单元”的概念,本质上就是“你告诉我要编译的文件中的所有代码加上它包含的所有文件”。

C 编译的原始流水线是首先运行“预处理器”以读入所有代码,处理宏和定义等,并将生成的代码输出到单个文件中(从内存中,.i中间文件)

foo.cpp

#include "foo1.h"
FOO {
    #include "foo2.h"
}

foo1.h

extern "C" int puts(const char*);
#define FOO int main()

foo2.h

puts("Hello, world\n");

g++ -Wall -E -o foo.i foo.cppg++ -Wall -o foo.exe foo.i 编译

foo.i 文件如下所示:

# 1 "foo.cpp"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 30 "/usr/include/stdc-predef.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/predefs.h" 1 3 4
# 31 "/usr/include/stdc-predef.h" 2 3 4
# 1 "<command-line>" 2
# 1 "foo.cpp"
# 1 "foo1.h" 1
extern "C" int puts(const char*);
# 2 "foo.cpp" 2

int main() {
# 1 "foo2.h" 1
 puts("Hello, world!\n");
# 5 "foo.cpp" 2
}

这是一个编译单元。如今,这个过程得到了简化,编译器本身内置了预处理器,但编译单元的概念仍然存在。

您的代码的问题在于您在头文件中定义 - 而不仅仅是声明 - IF_DEBUG_ENABLED,因此可能在多个编译单元中。当链接器试图将编译后的单元组合成一个可执行文件时,它会发现同名变量的多个实例。链接器无法判断它们应该是同一个东西。

要创建在多个编译单元(源文件)之间可见的全局变量或函数,您需要一个 header 声明/原型(prototype)和一个源文件定义/实例。

标题

extern bool IF_DEBUG_ENABLED; // variable declaration.
extern void herp();           // function prototype, but
void herp();                  // the extern is optional for functions.

为了能够使用其中任何一个,您现在需要用一个实现来支持它们。

源文件

bool IF_DEBUG_ENABLED = true;

假设您希望它是一个运行时变量。您的另一个选择是使用#define,就像您使用的守卫一样:

常量.h

#ifndef CONSTANT_H // poor choice, there may be a CONSTANT_H somewhere else.
#define CONSTANT_H 1

...
#define IF_DEBUG_ENABLED // comment out to disable

#endif

来源:

#if defined(IF_DEBUG_ENABLED)
   qDebug() << message;
#endif

此选项不允许您在运行时更改 IF_DEBUG_ENABLED,如果在编译时定义了 IF_DEBUG_ENABLED,则“qDebug() << message”代码仅写入可执行文件。

最后,除了使用 #if ... #define ... #endif 守卫方法,您可以在文件开头用一行替换所有三个:

常量.h:

#pragma once  //<<-- compiler implements a guard for you.

#include <QString>

class Debug
{  
public:
    static void Log(QString Message);
};

关于c++ - 头球后卫似乎不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18579340/

相关文章:

c++ - std::string 和 std::wstring 的 wdk ddk 编译器问题

c++ - C++ api 应该如何布局?

c - 不存在的目录中的多个定义

c++ - 为什么 Qt Creator 在包含的路径中找不到包含的 header - 即使 qmake 能够找到它们

c++ - 我可以在命名空间中包含头文件吗?

c++ - 这段 C++ 代码是如何工作的?未初始化的指针

c++ - 为什么结构体的 sizeof 不等于每个成员的 sizeof 之和?

c++ - 链接错误 : Duplicate Symbol

c++ - 正则表达式/Unix 工具,用于在 C++ 文件中的每个函数定义的开头之前插入一个新行

c++ - 可变参数函数,将值传递给另一个函数