使用多个标头和cpp文件有帮助

时间:2011-04-06 22:59:52

标签: c++ include compiler-errors linker-errors function-declaration

我正在使用DragonFireSDK创建应用,我想用.cpp和.h文件整理我的千元线应用

虽然

尝试做事,但我遇到了很多错误

所以我的app.cpp(主要的,必需的)看起来像这样

代码:

#include "DragonFireSDK.h"

#include "SaveData.h"
#include "Structures.h"
#include "Definitions.h"
#include "Variables.h"
#include "SaveData.h"

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "Functions.cpp"
#include "AppMain.cpp"
#include "AppExit.cpp"
#include "OnTimer.cpp"

#include&#34; SaveData.h&#34;通过#include&#34; Variables.h&#34; 都有类似的东西 代码:

#ifndef _HeaderName
#define _HeaderName
//STUFF HERE LIKE
#define player1 0
#define player2 1
//OR
typedef struct _number {
    int view;
    int number;
    bool able;
    int opacity;
};_number number[4];
//OR
int whoseturn;

int bet[5];
bool reachedmax[5];

int playerimg[5];
#endif

现在我可能已经做错了但是还有更多...... 我的AppMain.cpp,OnTimer.cpp等看起来像这样 (AppMain()等也是必需的功能) 代码:

#include "DragonFireSDK.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "Definitions.h"
#include "Structures.h"
#include "Variables.h"
#include "SaveData.h"

#include "Functions.cpp"

void AppMain() {
//STUFF HERE
};

现在这就是我认为问题所在...... Functions.cpp 代码:

#include "DragonFireSDK.h"

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "SaveData.h"
#include "Structures.h"
#include "Definitions.h"
#include "Variables.h"
//SOME FUNCTIONS
void   SavePlayerMoney();
void   SetInfo            (int idnum, bool actuallyset = false);
void   SwitchButton       (int idnum, bool makeactive=true);
void   DisableButton      (int idnum);
double round              (double number);

void SavePlayerMoney() {
    //...
}
void   SetInfo(int idnum, bool actuallyset) {
      //...
}
void   SwitchButton(int idnum, bool makeactive) {
      //...
}
void   DisableButton(int idnum){
      //...
}

现在我认为如果解决了所有问题后我得到的错误...... 代码:

1>AppMain.obj : error LNK2005: "void __cdecl SwitchButton(int,bool)" (?SwitchButton@@YAXH_N@Z) already defined in App.obj
1>AppMain.obj : error LNK2005: "double __cdecl round(double)" (?round@@YANN@Z) already defined in App.obj
1>AppMain.obj : error LNK2005: "void __cdecl SetInfo(int,bool)" (?SetInfo@@YAXH_N@Z) already defined in App.obj
1>AppMain.obj : error LNK2005: "int __cdecl Digits(int)" (?Digits@@YAHH@Z) already defined in App.obj

非常感谢任何帮助!

4 个答案:

答案 0 :(得分:3)

不要#include .cpp文件。

C编译模型是每个函数仅定义一次,即恰好在一个编译单元(即一个目标文件)中。您可以将每个源文件独立编译为单独的目标文件(#include - ing header 文件,以便编译器知道例如要使用的函数原型。然后,将这些单独的目标文件链接在一起,形成最终的可执行文件。

如果您{。}} .cpp文件,您将在多个编译单元中使用相同的定义功能(请记住#include基本上等同于复制 - 将内容粘贴到正在执行包含的文件中。所以链接器会变得混乱,并给你看到的消息。

<强>更新

哦,我发现问题是你没有#include的相应头文件。这个想法是你也写了一个Functions.cpp,类似于:

Functions.h

然后你#ifndef FUNCTIONS_H_ #define FUNCTIONS_H_ void SavePlayerMoney(); void SetInfo(int idnum, bool actuallyset); void SwitchButton(int idnum, bool makeactive); void DisableButton(int idnum); #endif 这个头文件,而不是.cpp文件。

答案 1 :(得分:2)

链接器抱怨因为函数被定义了不止一次。函数只能在一个转换单元中定义(cpp文件,在编译后它变成一个obj文件) - 除非它被声明为inline

您在其他单位中包含Functions.cpp,因此Function.cpp中的函数定义会复制到那些函数定义中,从而导致链接器出现问题。

解决方案是声明函数inline - 或者更好的是,在标题中声明它们(即Functions.h)和 define 他们在Functions.cpp。然后,这些功能的任何用户都可以#include Functions.h并且即使他们不知道他们的实现也可以访问这些功能。

声明一个函数,执行:int foo();,实际定义它,执行int foo() { your code goes here}.

答案 2 :(得分:1)

将函数声明移动到头文件。例如,看起来像Functions.h应该包含:

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

//SOME FUNCTIONS
void   SavePlayerMoney();
void   SetInfo            (int idnum, bool actuallyset = false);
void   SwitchButton       (int idnum, bool makeactive=true);
void   DisableButton      (int idnum);
double round              (double number);

#endif

然后Functions.cpp可以包含Functions.h而不是那些声明。某些头文件可能需要包含其他头文件才能获得适当的类型。

最后,永远不要#include * .cpp文件。

答案 3 :(得分:1)

我认为每个人都回答得非常好,所以我只是在大项目上给你我的C ++哲学,因为看起来你可能觉得它很有用。

总是分开函数声明和实现。 它会让你的生活变得更加轻松。在.h文件中声明函数原型,然后在.cpp文件中编写实现。

例如:

// mystuff.h
#ifndef MYSTUFF_H
#define MYSTUFF_H

int myFunction(int value, char letter);

#endif

在我的.cpp文件中:

// mystuff.cpp

#include "mystuff.h"

int myFunction(int value, char letter) {
    // insert implementation here
}

为什么这样?一个很好的理由是,当你的代码不起作用时(表面上看,这对于任何程序员来说都是不可避免的现实),你可以用替代实现替换你的.cpp文件而不修改你的代码结构。不仅如此,您还会发现各种技巧,这些技巧将依赖于分离声明和实现,这将大大简化您的生活。最重要的是,做到这一点。

尽可能尝试封装。 如果你正在做一个大项目(你会发现这对你遇到的大多数大项目都是如此),封装类似的函数,变量等将为你节省大量的时间和精力。看起来你正在制作一个游戏程序 - 你是否考虑过将每个玩家封装成一个Player或Human类,每个玩家都有类特定的功能?如果你是像我一样的C ++或Java迷,你会发现面向对象的方法是最有效的方法99次中有100次(1%的情况通常是你的辅助函数不适合的地方在您定义的任何对象中)。

此外,封装使您能够利用面向对象设计的两个基本原则 - 多态和继承。例如,你可以定义一个Player类,然后如果你的游戏涉及一个计算机玩家和一个人类玩家,你可以为每个人编写一个单独的类,它继承了Player的基本功能,但实现了一个Player的每个功能。不同的方式(即如果有一个makeMove函数,你会有一个不同于人的实现而不是计算机。因此,继承大大简化了你的工作)。 OO设计显然有很多吸引人的特性,但是对于我从你的代码中收集到的内容,我会说你会从这些代码中获益最多。

显然,这是我自己的哲学,而不是我想强行施加在你身上的哲学。但是希望你能从我的简洁漫游中获得一些有用的提示,以改善你编写代码的方式和/或避免长长的错误列表。祝你好运!