0

我正在使用 DragonFireSDK 制作一个应用程序,我想用 .cpp 和 .h 文件组织我的数千行应用程序

我在尝试做事情时遇到很多错误

所以我的 app.cpp (main, required one) 看起来像这样

代码:

#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 "SaveData.h" 到 #include "Variables.h" 都有类似代码:

#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

4 回答 4

4

不要#include.cpp 文件。

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

如果您#include使用 .cpp 文件,最终将在多个编译单元中定义相同的函数(请记住,这#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

然后你#include 这个头文件,而不是 .cpp 文件。

于 2011-04-06T23:01:12.087 回答
2

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

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

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

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

于 2011-04-06T23:05:49.323 回答
2

我认为每个人都很好地回答了这个问题,所以我将向您介绍我关于大型项目的 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 迷,您会发现面向对象的方法是最有效的方法 100 次中有 99 次(1% 的情况通常是您的辅助函数并不真正适合在您定义的任何对象中)。

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

Obviously, this is my own philosophy and not one that I wish to forcefully impose on you. But hopefully you will take a few helpful tips out of my terse rambling to improve the way you write code and/or avoid long lists of errors. Best of luck!

于 2011-04-06T23:25:34.663 回答
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 文件。

于 2011-04-06T23:07:41.427 回答