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

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

我将 constant.h debug.h 包括在我的 main.cpp 中,以访问该变量。

当我编译时,错误显示**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

/-debug.h-/
#ifndef DEBUG_H
#define DEBUG_H

#include <QString>

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

#endif // DEBUG_H

/-debug.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,而不是在头文件中定义了ojit_code,因此有可能在多个编译单元中进行定义。当链接器尝试将已编译的单元组合成可执行文件时,它将查找具有相同名称的变量的多个实例。链接器无法告诉他们它们应该是同一件事。

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

header
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,就像您使用的 guard 一样:

常数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()<
最后,除了使用#if ... #define ... #endif保护方法,您还可以在文件开头用一行替换所有三个:

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

#include <QString>

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

10-08 08:23
查看更多