标题守卫似乎不工作? [英] Header guards do not seem to work?

查看:140
本文介绍了标题守卫似乎不工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



debug.cpp 以访问该变量。



我包括 constant.h 调试。



当我编译时,显示的错误<$ c $ 在我 main.cpp c> ** multiple definition ** of ** IF_DEBUG_ENABLED ** 。



请告诉我实际上我做错了什么。此外,请注意,这是我第一次使用第一个c / c ++ 应用程序的第一天。我从来没有在学校读过。



我的代码来源如下:
as



/ - constant.h - /

  #ifndef CONSTANT_H 
#定义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

/ cpp - /

  #includeconstant.h
#includedebug.h

#includeQDebug

static void日志(QString Message)
{
if(IF_DEBUG_ENABLED)
qDebug()< <信息; // It says problem is here
}

/ - main.cpp - /

  #includeconstant.h
#includedebug.h

int main(int argc,char * argv [])
{
Debug :: Log(新应用程序已运行);
}


解决方案

C和C ++一个编译单元,这本质上是你告诉我要编译的文件中的所有代码加上它包括的所有文件。



C编译的原始管道是首先运行预处理器读取所有代码,处理宏和定义等,代码转换为单个文件(从内存,中间的.i文件)



foo.cpp

  #includefoo1.h
FOO {
#includefoo2.h
}
pre>

foo1.h

  externCint puts const char *); 
#define FOO int main()

foo2.h

  puts(Hello,world\\\
);

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



c $ c> foo.i 文件如下所示:

 #1foo.cpp 
#1< command-line>
#1/usr/include/stdc-predef.h1 3 4
#30/usr/include/stdc-predef.h3 4
#1/ usr /include/x86_64-linux-gnu/bits/predefs.h1 3 4
#31/usr/include/stdc-predef.h2 3 4
#1< command- line> 2
#1foo.cpp
#1foo1.h1
externCint puts(const char *);
#2foo.cpp2

int main(){
#1foo2.h1
puts(Hello,world!\ n);
#5foo.cpp2
}

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



你的代码的问题是您正在定义 - 而不仅仅是在头文件中声明 - IF_DEBUG_ENABLED ,因此可能在多个编译单元中。当链接器试图将编译的单元合并成一个可执行文件时,它会发现同名变量的多个实例。



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



 code> extern bool IF_DEBUG_ENABLED; //变量声明。 
extern void herp(); // function prototype,but
void herp(); // extern对于函数是可选的。

为了能够使用这些,现在需要用一个实现来备份它们。 / p>

源文件

  bool IF_DEBUG_ENABLED = true; 

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



constant.h

  #ifndef CONSTANT_H //差的选择,在其他地方可能有一个CONSTANT_H。 
#define CONSTANT_H 1

...
#define IF_DEBUG_ENABLED //注释掉以禁用

#endif

来源:

  (IF_DEBUG_ENABLED)
qDebug()<<信息;
#endif

此选项不允许在运行时更改IF_DEBUG_ENABLED,如果在编译时定义了IF_DEBUG_ENABLED,则qDebug()<<

constant.h:

  #pragma once //<<  - 编译器为您实现了保护。 

#include< QString>

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


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");
}

解决方案

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);
};

这篇关于标题守卫似乎不工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆