如何为头文件声明`#include`以避免错误lnk2005`

时间:2014-10-26 19:23:15

标签: c++ visual-studio-2012 linker

我创建了一个新的WIN32 C ++项目。我还没有触及主文件中的任何代码,并开始在不同的文件中编写我的代码objectsFW.cpp文件的定义位于文件objectsFW.h中。

objFW.h看起来像:

#pragma once

double g;

typedef struct {
    double x;
    double y;
}Vector;

typedef struct {
    //...
}BoundingBox;

typedef struct {
    //...
}Ball;

Vector operator + (Vector a, Vector b) {
    //...
}

Vector operator - (Vector a, Vector b) {
    //...
}

还有一些运算符定义,以及函数的声明。 我将头文件包含在源文件(objectsFW.cpp)中,并将其添加到Resources.h文件中,以便我的代码可以在主程序中使用。

我收到链接器错误:

Error   1   error LNK2005: "struct Vector __cdecl operator*(struct Vector,double)" (??D@YA?AUVector@@U0@N@Z) already defined in ObjectsFW.obj   C:\testC\ObjectsCollision\ObjectsCollision\ObjectsCollision.obj ObjectsCollision
...
Error   4   error LNK2005: "struct Vector __cdecl operator+(struct Vector,struct Vector)" (??H@YA?AUVector@@U0@0@Z) already defined in ObjectsFW.obj    C:\testC\ObjectsCollision\ObjectsCollision\ObjectsCollision.obj ObjectsCollision

等等。

我知道发生这种情况是因为#include "objectFW.h"行出现了两次(每个.cpp文件中都有一次)。问题是声明头文件以避免链接器错误的正确方法是什么?


UPDATE:

将操作员功能转为inline大多数错误修复后,仍有一个程序包含该行:

double g;

错误是:

Error   1   error LNK2005: "double g" (?g@@3NA) already defined in ObjectsCollision.obj C:\testC\ObjectsCollision\ObjectsCollision\ObjectsFW.obj    ObjectsCollision

(在Visual Studio 2012上工作)

2 个答案:

答案 0 :(得分:4)

关于全局变量:
1.不要使用它们。想想封装数据隐藏 2.如果必须使用它们,请定义全局输入1源文件并放置" extern"在头文件中。

例:
header_file.hpp:

  extern unsigned int deadly_global;

source_file.cpp:

  unsigned int deadly_global;

隐藏全局变量的更好方法

控制(隐藏)全局变量的更好方法是将使用该变量的所有代码放在同一个源文件中,并将变量声明为static

  static unsigned int variable_shared_by_many_functions = 0;
  void f1(void)
  {
    variable_shared_by_many_functions = 42U;
  }

  void f2(void)
  {
    std::cout << "Value of shared variable: "
              << variable_shared_by_many_functions
              << "\n";
  }

使用Getter和Setter控制全局变量

如果必须在多个源文件中的函数之间共享变量,则更安全的技术是在一个源文件中将变量声明为静态,并声明函数(接口)以访问它。

  static int dangerous_variable = 0;

  int accessor(void)
  {
     // Return a copy of the varible.
     return dangerous_variable;
  }

  void setter(int new_value)
  {
    if ((new_value / 5) != 1)
    {
       dangerous_variable = new_value;
    }
  }

此技术允许您在设置变量时放置过滤器或其他控件。

答案 1 :(得分:2)

放入标题:

extern double g;

在.cpp中:

double g;

这样,包含标题的每个文件都会知道有一个变量g,但它只会在一个地方声明。