Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 抛接球会导致连接错误_C++_Visual Studio 2008_Templates_Try Catch_Linker Errors - Fatal编程技术网

C++ 抛接球会导致连接错误

C++ 抛接球会导致连接错误,c++,visual-studio-2008,templates,try-catch,linker-errors,C++,Visual Studio 2008,Templates,Try Catch,Linker Errors,我得到了以下类型的链接错误: Festival.obj:错误LNK2019: 未解析的外部符号“公共: void _u此调用树::添加(类价格&)” (?添加@$Tree@VPrice@@@@QaexavPrice@@@Z) 在函数中引用 __捕获$?AddBand@Festival@@QAE?AW4StatusType@@HHH@Z0美元 我过去认为这与试捕机制有关,但后来有人告诉我不是这样。这是问题的更新版本 我使用的是VisualStudio2008,但在g++中也有类似的问题 有关守则:

我得到了以下类型的链接错误:

Festival.obj:错误LNK2019: 未解析的外部符号“公共: void _u此调用树::添加(类价格&)” (?添加@$Tree@VPrice@@@@QaexavPrice@@@Z) 在函数中引用 __捕获$?AddBand@Festival@@QAE?AW4StatusType@@HHH@Z0美元

我过去认为这与试捕机制有关,但后来有人告诉我不是这样。这是问题的更新版本

我使用的是VisualStudio2008,但在g++中也有类似的问题

有关守则:

在Festival.cpp中

#include "Tree.h"
#include <exception>

using namespace std;

class Band{
public:
    Band(int bandID, int price, int votes=0): bandID(bandID), price(price), votes(votes){};
...
private:
...

};

class Festival{
public: 
    Festival(int budget): budget(budget), minPrice(0), maxNeededBudget(0), priceOffset(0), bandCounter(0){};
    ~Festival();
    StatusType AddBand(int bandID, int price, int votes=0);
    ...

private: 
    Tree<Band> bandTree;
    ...

};

StatusType Festival::AddBand(int bandID, int price, int votes){
    if ((price<0)||(bandID<0)){
        return INVALID_INPUT;
    }
    Band* newBand=NULL;
    try{
        newBand=new Band(bandID,price-priceOffset,votes);
    }
    catch(bad_alloc&){return ALLOCATION_ERROR;}
    if (bandTree.find(*newBand)!=NULL){
        delete newBand;
        return FAILURE;
    }
bandTree.add(*newBand);
....
}
#包括“Tree.h”
#包括
使用名称空间std;
班级乐队{
公众:
Band(intbandid,intprice,intvoces=0):bandID(bandID),price(price),voces(voces){};
...
私人:
...
};
班级节{
公众:
节日(int预算):预算(预算),最小价格(0),最大需要预算(0),价格偏移(0),带计数器(0){};
~Festival();
StatusType AddBand(int-bandID、int-price、int-Voces=0);
...
私人:
树带树;
...
};
StatusType Festival::AddBand(整数bandID、整数价格、整数投票){

如果((price您确定
try
/
catch
与此有关吗?如果您只是注释掉
try
catch
行,将其余代码保持原样,然后构建它,会发生什么


这可能只是因为您缺少从链接行定义
Tree::add(class Price&)
的库。

更新:将树函数与基元类型一起使用不会导致链接错误。
我根据所说的一些事情更新了我的问题。

有Tree.cpp吗?如果有,可能您忘记链接了?Tree::add的实现在哪里? 此外,我看不出您在哪里调用Tree::add。我想它应该在try语句中,就在new之后

只是提醒一下:

对于大多数编译器(即进行单独编译的编译器),在编译使用模板类的源文件期间,模板类的成员函数的实现必须可见。通常,人们遵循这一规则,将成员函数的实现放在头文件中

也许Tree::add不在头文件中?那么在讨论的案例中,一个可能的解决方案是将Tree::add实现放在头文件中

常规类和模板类之间存在差异,因为模板类不是“真实”类-它是一个模板。如果您将树类定义为常规类,编译器可能会立即使用您的代码。对于模板,编译器首先“编写”对于真正的类,请使用您提供的类型替换模板参数。现在,编译器逐个编译cpp文件。他不知道其他cpp文件,并且无法使用其他cpp文件中的任何内容。假设Tree:add的实现如下所示:

void Tree::add(T& newData)
{
    newData.destroyEverything();
}
只要你的T方法销毁了所有东西,这是完全合法的。当编译器编译Class.cpp时,它希望确保你不处理它不知道的任何东西。例如,
Tree
将不起作用,因为int没有销毁所有东西。编译器将尝试用int而不是T编写你的代码,并发现这一点代码不会编译。但由于编译器只“看到”当前cpp及其包含的所有内容,因此无法验证add函数,因为它位于单独的cpp中

这不会有任何问题

void Tree::add(int& newData)
{
    newData.destroyEverything();
}

在一个单独的cpp中实现,因为编译器知道int是唯一可接受的类型,并且可以“依靠自己”在编译Tree.cpp时找到错误。

您得到的是链接错误,而不是编译器错误。这告诉我们编译器知道什么类型的函数
Tree::add()
是,但没有定义。在Tree.h中,我看到了add()函数的声明,但没有定义。我觉得很奇怪;有人知道Tree.h来自哪里吗

通常模板类在include文件中带有成员函数定义,因为函数必须在某处实例化,最简单的事情是编译器在使用时实例化,并让链接器对其进行排序。如果定义在Tree.h中,我希望一切都按计划进行

因此,我要冒险指出,这些定义是在一个单独的文件中,而不是链接进来的,并且其他地方有一些规定可以实例化基本类型,如
。这大概是为了简化编译,因为通常这些东西是在多个地方编译的,这需要时间

在这种情况下,您需要做的是找到实例化
树的位置,并为类添加一个实例化

我在这里可能有点离谱,但我的解释确实符合你给出的事实

在第一次评论后编辑

模板比普通函数要复杂一些,这通常不是一个真正的问题。如果所有调用的定义都在Tree.h中,那么Festival.cpp将能够实例化
Tree
,一切都会很酷。这是通常的技术,您遇到这个问题是因为您没有使用它

当你编写一个函数时,它会被编译,链接器会找到它。任何调用该函数的例程都需要知道函数原型,这样它就会知道如何调用它。当你编写一个模板时,你不会编写任何将直接进入程序的内容,但是任何使用模板的行为都会被视为编写所有函数

因此,必须在程序的某个地方使用
Tree
,才能编译
Tree::add()
函数。在实例化
Tree
时,编译器必须能够使用
Tree::add
的定义,否则编译器就不知道要编译什么
void Tree::add(int& newData)
{
    newData.destroyEverything();
}
  Band* newBand=NULL;
    try{
        newBand=new Band(bandID,price-priceOffset,votes);
    }
    catch(bad_alloc&){return ALLOCATION_ERROR;}
Band * newBand = new Band ( bandID, price - priceOffset, votes );
Band newBand( bandID, price - priceOffset, votes );
priceTree.add(*newPriceNode);
priceTree.add(newPriceNode); //no "*" before "newPriceNode"