#pragma once或包含不在extern func上工作的警卫

时间:2011-08-10 04:38:38

标签: c++ visual-studio header

我的项目遇到了一个非常奇怪(又烦人)的链接器错误。

比方说,我有文件KernelExports.h:

#pragma once

extern "C"
{
    DWORD* KeTimeStampBundle;
    DWORD KeGetCurrentProcessType();
    //etc...
}

然后我在我的stdafx.h中#include然后添加#include "stdafx.h"我所有的* .cpp文件。问题是,现在每当我构建时,我都会遇到链接器错误:LNK2005: KeTimeStampBundle already defined in stdafx.obj。这不应该发生,因为头文件只包含在一个文件中并受到包含保护的保护。一旦我注释掉整个extern "C"块,错误就会停止,所以我知道这就是导致问题的原因。

更奇怪的是,当我将所有这些源文件添加到它构建的新项目时没有任何问题。我不知道这里有什么问题,任何人都可以启发我吗?

我的IDE是Visual Studio 2008。

2 个答案:

答案 0 :(得分:5)

DWORD* KeTimeStampBundle;

这不会声明一个函数。它声明了并定义了一个名为DWORD*的{​​{1}}类型的对象。如果将此头文件包含在多个源文件中,则您将拥有此对象的多个定义(每个源文件中包含一个头文件)。

包括警卫和KeTimeStampBundle确保某些内容仅在给定翻译单元中定义(源文件)。它们对多个翻译单元的定义方式没有影响。

答案 1 :(得分:4)

#pragma once不会阻止您的文件多次出现在项目中,因此不会在同一文件中多次包含该文件。因此,a.cppb.cpp可以包含一次文件,并定义KeTimeStampBundle两次。

要解决此问题,请将KeTimeStampBundleKeGetCurrentProcessType等的定义放入.cpp文件中,并将extern DWORD* KeTimeStampBundle等放入标题中。

请注意,这仅适用于 definitions ,而不适用于声明extern ...和函数原型是声明,所以它们可以多次完成,但定义只能在整个项目中出现一次,覆盖所有.cpp个文件。