问题
I have declared some constant variable in seperate header (i.e., constant.h).
I include the constant.h in my debug.cpp as to access the variable.
I include the constant.h, debug.h in my main.cpp as to access the variable.
When I compile, the error it shows **multiple definition** of **IF_DEBUG_ENABLED**
.
Kindly tell me what is actually I'm doing wrong. Also, please note that this is my first day on my very first c/c++ application. I've never even read it in school.
My code source is as follows: as
/-- 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");
}
回答1:
C and C++ have the concept of a "compilation unit", which is essentially "all the code in the file you tell me to compile plus all the files it includes".
The original pipeline for C compilation was to first run the "pre-processor" to read in all of the code, process the macros and defines etc, and output the resulting code into a single file (from memory, a .i file for intermediate)
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");
Compile with g++ -Wall -E -o foo.i foo.cpp
and g++ -Wall -o foo.exe foo.i
The foo.i
file looks like this:
# 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
}
This is a compilation unit. The process is simplified these days, the pre-processor being built in to the compiler itself, but the notion of a compilation unit still remains.
The problem with your code is that you are defining - not just declaring - IF_DEBUG_ENABLED
in a header file, and thus potentially in multiple compilation units. When the linker tries to combine the compiled units into an executable, it's finding multiple instances of a variable with the same name. The linker has no way to tell that they were supposed to be the same thing.
To create a global variable or function visible between multiple compilation units (source files), you need a header declaration/prototype and a source-file definition/instance.
header
extern bool IF_DEBUG_ENABLED; // variable declaration.
extern void herp(); // function prototype, but
void herp(); // the extern is optional for functions.
To be able to use either of these, you now need to back them up with a implementation.
source file
bool IF_DEBUG_ENABLED = true;
This is, assuming that you want it to be a run-time variable. Another option you have is to use a #define, just like the guard you were using:
constant.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
source:
#if defined(IF_DEBUG_ENABLED)
qDebug() << message;
#endif
This option doesn't allow you to change IF_DEBUG_ENABLED during run-time, the "qDebug() << message" code is only written to the executable if IF_DEBUG_ENABLED is defined at compile time.
Lastly, instead of using the #if ... #define ... #endif guard method, you can replace all three with a single line at the start of the file:
constant.h:
#pragma once //<<-- compiler implements a guard for you.
#include <QString>
class Debug
{
public:
static void Log(QString Message);
};
回答2:
You should put the definition in a .cpp file, not in a header. In the header you should only put declarations : extern const bool IF_DEBUG_ENABLED;
This will tell any code #include
ing it that there exist some global variable named IF_DEBUG_ENABLED
. Inside debug.cpp you should put the actual definition.
The guards only help to prevent you from defining multiple times in a single compilation unit. But you have two compilation units: debug.cpp (plus headers) and main.cpp (plus headers). which means you have multiple definitions of the variables in the header.
You have another problem: you implement a static function Log()
but you should implement a static class-method Debug::Log()
.
来源:https://stackoverflow.com/questions/18579340/header-guards-do-not-seem-to-work