C++错误 LNK2019和致命错误LNK1120:有1个未解析的外部符号。

3
我正在尝试为学校的作业任务工作,并且在任务要求之上进行了创新 -> 我创建了一个“列表”类。在添加“add()”方法到程序中以及“newIncomeTax()”方法后,我遇到了这两个错误:
错误 LNK2019:无法解析的外部符号“public: void __thiscall List::add(class IncomeTax *)”(?add@List@@QAEXPAVIncomeTax@@@Z),在函数_main driver.obj中引用

致命错误 LNK1120:1 个无法解析的外部
我希望这将足够让任何人帮助我:
注意:下面的函数不按原始代码中的顺序排列 (如果可能是问题,我可以提供我正在使用的所有代码)

list.h

#ifndef LIST_H
#define LIST_H

#include "IncomeTax.h"
class List
{
private:
    IncomeTax * First;
    IncomeTax * Last;
    int num_in_list;
public:
    List () { num_in_list = 0; First = NULL; Last = NULL; }
    int get_num_in_list() { return num_in_list; }
    IncomeTax * getFirst() { return First; }
    IncomeTax * getLast() { return Last; }
    void del_frnt ();
    void push_front (IncomeTax *);
    void push_back (IncomeTax *);
    void del_last ();
    void add (IncomeTax*);
    IncomeTax * pop_back ();
    IncomeTax * pop_front ();
    IncomeTax * get (int);
};
#endif

注意:根据我所看到的,我所创建的列表与默认列表的行为类似。

list.cpp中的“add”方法

void List:: add (IncomeTax * IncomeTax_to_be_added) {
    if (num_in_list == 0) { First = IncomeTax_to_be_added; Last = IncomeTax_to_be_added; }
    else if (num_in_list != 0 ) {
        Last->setNext(IncomeTax_to_be_added);
        IncomeTax_to_be_added->setPrevous(Last);
        Last = IncomeTax_to_be_added;
    }
    num_in_list++;
}

IncomeTax.h

#ifndef INCOME_TAX
#define INCOME_TAX

#include <iostream>
#include <string>
#include "conio.h"
#include <cassert>
using namespace std;

class IncomeTax {
private:
    double incm;
    double ajIncm;
    double subtract;
    double taxRate;
    double add;
    bool married;

    void calcIncome_m ();
    void calcIncome_s ();
public:
    IncomeTax () { incm = 0; subtract = 0; taxRate = 0; add = 0; add = false; }
    // married -> is by default false
    void setmarried ( bool stats ) { married = stats; }
    void setIncm (double in ) { incm = in; }
    void setSubtract ( double sub ) { subtract = sub; }
    void setTaxRate ( double rate ) { taxRate = rate; }
    void setAdd ( double Add ) { add = Add; }
    void setAjIncome ( double AJincome ) { ajIncm = AJincome; }

    bool getmarried () { return married; }
    double getIncm () { return incm; }
    double getsubtract () { return subtract; }
    double getTaxRate () { return taxRate; }
    double getAdd () { return add; }
    double getAJincome () { return ajIncm; }
    void calcIncome ();
    void pintIncome ();
};

#endif

IncomeTax.cpp

#include "IncomeTax.h"
using namespace std;

void IncomeTax::calcIncome(){
    assert (incm != 0);
    if (married) { calcIncome_m(); }
    if (!married) { calcIncome_s(); }

    ajIncm = (incm - subtract);
    ajIncm -= (ajIncm * taxRate);
    ajIncm += add; 
}

void IncomeTax::calcIncome_m() {
    assert (incm != 0);
    ... huge nested if statements ... 
    they set subtract, add, taxRate...
}

void IncomeTax::calcIncome_s() {
    assert (incm != 0);
    ... huge nested if statements ... 
    they set subtract, add, taxRate...
}

void IncomeTax::pintIncome () {
    assert (incm != 0);
    assert (ajIncm != 0);

    std::cout.precision(2);
    cout << "\tTaxable Income: " << incm << endl;
    cout << "\tAjusted Income: " << ajIncm << endl;
    cout << "\tTax: " << (incm - ajIncm) << "\n" << endl;
}

Driver.cpp

#include <conio.h>
#include <iostream>
#include <string>
#include <cassert>
#include "IncomeTax.h"
#include "List.h"
using namespace std;

void getMaritalStatus( IncomeTax new_tax) {
    bool done = false;
    char stt = ' ';
    while ( !done ) {
        cout << "\nPlease declare weather you are filing taxes jointly or single" << "\n";
        cout << "\t's' = single\n\t'm' = married" << endl;
        stt = getch();
        if ( stt == 's' || stt == 'm' ) { done = true; }
        if ( stt == 's' ) { new_tax.setmarried(true); }
        if ( ! (stt == 's' || stt == 'm') ) { cout << "\nyou have entered an invald symbol... \n" << endl; }
        if(cin.fail()) { cin.clear(); }
        }
    }


void get_Income ( IncomeTax new_tax) {
    double _incm = 0;
    char status = ' ';
    bool done = true;
    while ( done ) {
        cout << "Please enter your TAXABLE INCOME:" << endl;
        cin >> _incm;
        if ( _incm > 0 ) { new_tax.setIncm(_incm); done = false; }
        if ( _incm <= 0 ) { cout << "\nthe number you entered was less than zero\nplease enter a valad number...\n" << endl; } 
        if(cin.fail()) { cin.clear(); }
    }
    }

IncomeTax newIncomeTax () {
    IncomeTax new_tax;
    IncomeTax * temp;
    get_Income(new_tax);
    getMaritalStatus(new_tax);
    new_tax.calcIncome();
    return new_tax;
}

bool again () {
    bool done = false, answer = false;
    char yn = ' ';
    while ( !done ) {
        cout << "\nWould you like to calculate another Income tax? (y/n)" << endl;
        yn = getch();
        if ( yn == 'y' || yn == 'n' ) { done = true; }
        if ( yn == 'y' ) { return false; }
        if ( yn == 'n' ) { return true; }
        if ( ! (yn == 's' || yn == 'n') ) { cout << "\nyou have entered an invald symbol... \n" << endl; }
        if(cin.fail()) { cin.clear(); }
        }
    }

int main () {
    IncomeTax new_tax;
    List L;
    bool done = false;
    while (!done) {
        IncomeTax temp = newIncomeTax();
        IncomeTax * ptr = &temp;
        L.add(ptr);
        done = again();
        };

    return 0;
};

我知道有许多更好的方法来使用“if”语句 -> 我只是决定使用if语句会更有效率 -> 教授已经说过没有必要超越这个范围。

由于这是作业,我希望能得到一些关于如何使用更好的编程技巧的反馈。谢谢!

我正在使用VS Express 2008 C++。


1
你是把所有的代码都放在一个文件里吗(就像原来的样子)?还是你正在正确地声明类在头文件中,然后将它们包含并引用它们? - dirkgently
@dirkgently:是的,我已经把它们都放在了.ccp和.h文件中(添加到原始帖子中)。 - Wallter
相关链接:https://dev59.com/gkvSa4cB1Zd3GeqPcz1B#2038233 - Roger Pate
Wallter:请确保您发布的代码顺序与文件中的顺序相同。如果您能够发布List.hpp、List.cpp和driver.cpp的确切内容,那会很有帮助;如果您觉得这些文件太长了,那么请复制到一个新文件夹并开始剥离代码,以创建一个更小的测试用例进行发布。 - Roger Pate
如果您不提供您正在使用的确切代码(完整的),那么很难弄清楚您的代码发生了什么。这里似乎没有List.cpp文件。相信我,没有人想“窃取”您的列表代码,因为可能有很多实现方法更有效率。我想帮助您,但我不能只是复制和粘贴代码,然后就拥有我需要的一切......我必须思考并意识到缺少了哪些部分。 - Brian T Hannan
显示剩余3条评论
3个回答

2
由于这是作业,我希望能得到一些反馈,以便我可以使用更好的编程技术。感谢! 创建单独的头文件/实现文件用于您的类,不要将它们全部放在单个头文件中。并将您的 main 放在一个单独的实现文件中(如果您愿意,可以称其为 main.cpp)。 剪切所有未使用的函数,并尝试创建最小的示例来复制您的错误 - 这将帮助您轻松解决问题,而无需每时每刻回到 SO。一次添加一个函数,看看它是否编译通过,然后再继续下一个,反复执行。添加函数时另一个好主意是使用存根 - 仅用于检查是否未命中任何这些未解决的符号错误的空函数(当您开始时)。您还需要学习语法 - 您不需要在 while 的结束括号后加上分号。您还将了解成员按声明顺序初始化(因此您的 int 成员理想情况下应跟随您的 IncomeTax 成员)。您需要知道什么是初始化列表。您还需要了解前向声明。简而言之,您需要一本书和大量练习。这里是您的代码稍微重构了一下,使用了我上面解释的一些东西:
class IncomeTax {};

class List
    {
    private:
        IncomeTax * First;
        IncomeTax * Last;
        int num_in_list;
    public:
        List () : 
            First(NULL), 
            Last(NULL),
                        num_in_list (0)
        {}
        ~List() 
        {
            // free First and Last ?
        }
        void add (IncomeTax*) {}    
};

    int main () {
        IncomeTax new_tax;
        List L;
        bool done = false;
        while (!done) {
            IncomeTax temp;
            L.add(&temp);
                done = true;
        }

        return 0;
    }

哦,是的,我把所有的类相关内容都放在了各自的.cpp和.h文件中 - 并且添加了函数->这就是我一直在做的,但就在这时我遇到了这个错误。 - Wallter
@Walter:你能精简代码并尝试复现问题吗?看看我更新的帖子中的想法。 - dirkgently
@dirkgently:问题在于当我遇到这些错误时,它们没有行号...除了“1” - 这是我写的注释 --- 我提供的代码就是我在编辑时遇到错误的代码。 - Wallter
@Walter:你的问题可能只是一个简单的打字错误。例如:看一下 IncomeTax::pintIncome() -- 你可能在头文件中声明了一个 printIncome() 方法!检查拼写。 - dirkgently

1

你在这里没有告诉我们其他的事情,因为这应该是无缝链接的(在这里确实是这样)。我只是将List类声明移动到main()之前,以避免在编译主函数时声明该类,但除此之外一切都可以正常编译。

// Something declared in this order (in the same file or through .h files) should compile & link correctly
class IncomeTax { ... };
class List { ... };
int main() { ... };

我的driver.cpp(包含main函数)的声明如下:#include <iostream> #include <string> #include <cassert> #include "IncomeTax.h" #include "List.h" using namespace std; 所以我不认为这是问题...但也有可能。 - Wallter

1

看起来您可能忘记将IncomeTax对象文件(IncomeTax.o,IncomeTax.obj等)添加到链接命令行中,链接器告诉您找不到方法定义。

您可以通过临时创建一个包含所有代码顺序复制的单个“whole_project.cpp”文件来测试。如果以这种方式编译和链接正确,则只需编辑makefile / IDE项目文件/手动命令行,以指定它还需要包括对象文件。

它仅显示一个错误,因为您实际上只调用了add函数,而没有调用列表类中的任何其他非内联函数。

最后,请仔细检查您用于向列表添加项目的逻辑。我认为您添加的临时项会导致问题,因为对象在while循环进入其下一个迭代时就消失了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接