3

I am trying to work on a homework assignment for school and am going above what the teacher is asking for the assignment -> I have created a "list" class. I keep running into these two errors after adding the 'add()' method to the program - along with the 'newIncomeTax()' methods

error LNK2019: unresolved external symbol "public: void __thiscall List::add(class IncomeTax *)" (?add@List@@QAEXPAVIncomeTax@@@Z) referenced in function _main driver.obj

and

fatal error LNK1120: 1 unresolved externals

I hope this will be enough code for anyone trying to help me:

note: the functions below are not in the order that they appear in the original code (if that may be the problem I can provide all the code that i'm using)

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

note: from what I've seen the list that **I've** made behaves similarly to the default

the 'add' method from list.cpp

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;
};

I know that there are many better ways to do the 'if' statements -> i just decided that it would be efficient to just use the if statments -> the professor has stated that there is no need to go beyond this.

Since this is homework I would love to get some feed back on ways that I can use better programing techniques. thanks!

I'm using VS express 2008 C++

Wallter
  • 4,275
  • 6
  • 29
  • 33
  • 1
    Do you have all this in one single file (and as-is)? Or, are you doing the right thing by declaring classes in a header, including them and then referencing them? – dirkgently Jan 15 '10 at 16:53
  • @dirkgently: yeah, I've got them all in the .ccp and .h files (added to original post) – Wallter Jan 15 '10 at 17:19
  • the last errors i was trying to fix were the fact that newIncomeTax() returns a IncomeTax - but 'add()' takes a pointer as a parameter – Wallter Jan 15 '10 at 17:26
  • Related: http://stackoverflow.com/questions/2037880/how-can-i-avoid-including-class-implementation-files/2038233#2038233 –  Jan 15 '10 at 17:44
  • Wallter: Please do keep posted code in the same order as you have it in your files. If you could post the exact contents of List.hpp, List.cpp, and driver.cpp, that would help; and if you feel they're too long, then copy them to a new folder and start stripping out code to create a smaller test case which you can post. –  Jan 15 '10 at 18:04
  • It's difficult to figure out what is going on in your code if you don't give us the exact code you are working with (in full). You don't appear to have the List.cpp file here. Trust me, no one wants to "steal" your list code as there are plenty of implementations out there that are probably more efficient. I wanted to help you, but I couldn't just copy and paste the code and have everything I needed ... I would have to think about it and then realize that pieces are missing. – Brian T Hannan Jan 15 '10 at 18:35
  • Wallter: Thanks for the code. What is the exact command that generates the link error you see? If you're using make, make prints the commands before it executes them, by default; but I see you're using VC---are you using it from the command line or in the IDE? If you're in the IDE I can't remember if it shows the exact commands, which would be a shame if it doesn't. –  Jan 15 '10 at 18:41
  • It's the "L.add(ptr);" line that throws out the program - when it's commented out the program runs fine – Wallter Jan 17 '10 at 03:46

3 Answers3

2

Since this is homework I would love to get some feed back on ways that I can use better programing techniques. thanks!

Create separate headers/implementation files for your classes. Don't put all of them in a single header. And put your main in a separate implementation file (call it main.cpp, if you will).

Cut out all the functions that you are not using, and try to create the minimal example that reproduces your error -- that'll help you figure out your issues easily and without needing to come back to SO every now and then. Add one function at a time and see if it compiles, then move on to the next, rinse and repeat.

Another good idea when adding functions is to use stubs -- empty functions just to check if you don't hit any of these unresolved symbol errors (when you're starting out).

You will also need to learn about the syntax -- you don't need a semi-colon after the ending brace of while. You will also learn that members are initialized in the order in which they are declared (so your int member should ideally follow your IncomeTax members). You will need to know what initializer-lists are. And you will need to know about forward declaring.

In short, you will need a book and lots of practice. Here's your code refactored a bit using some of the things I explained above:

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;
    }
dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • oh, yeah, i've got all the class stuff in the respective .cpp and .h files - with the adding functions-> that's what I've been doing but that's when i ran into this error – Wallter Jan 15 '10 at 17:03
  • @Walter: Can you cut down your code and try to reproduce the problem -- see my updated post for ideas. – dirkgently Jan 15 '10 at 17:08
  • @dirkgently: the problem with that is that when i get these errors they don't have a line number... except '1' - which is a comment that I wrote the code --- the code i provided is the code i was editing when i got the error – Wallter Jan 15 '10 at 17:16
  • @Walter: Your problem could be as simple as a typo. E.g: Look at `IncomeTax::pintIncome()` -- you probably declared a `printIncome()` method in the header! Check for spellings. – dirkgently Jan 15 '10 at 20:38
1

There's something else you're not telling us here since this should link flawlessly (it did here). I just moved the List class declaration before main() to avoid the class is declared when compiling main but otherwise everything compiles fine.

// Something declared in this order (in the same file or through .h files) should compile & link correctly
class IncomeTax { ... };
class List { ... };
int main() { ... };
Francis Boivin
  • 255
  • 1
  • 7
  • my declarations for driver.cpp (contains main) go like this: #include #include #include #include "IncomeTax.h" #include "List.h" using namespace std; so i don't think that's the problem... but it might – Wallter Jan 15 '10 at 17:09
1

It looks like you may have forgotten to add the IncomeTax object file (IncomeTax.o, IncomeTax.obj, etc) into your link command line, and the linker is telling you that it can't find the method definition.

You can test this by temporarily creating a single "whole_project.cpp" file that contains all the code copy-pasted sequentially. If it compiles and links correctly that way, then you just need to edit your makefile/IDE project file/manual command line to specify that it also needs to include the object file.

It only shows the one error because you're only actually calling the add function and none of the other non-inline functions within the list class.

Finally, double check the logic you're using to add items to the list. I believe the temporary you're adding will cause problems since the object goes away as soon as the while loop enters its next iteration.

Mark B
  • 95,107
  • 10
  • 109
  • 188