Undefined reference to constructors and destructor.

Mar 5, 2011 at 5:55pm
I'm having some trouble with a class I'm writing for my midterm. For some reason, I wrote out the constructor and destructor and I'm getting errors when I compile saying there is an undefined reference to them. Anyone know what's wrong?

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
    Project: CIS 225 - Midterm
    Author: packetpirate
    Build #: 1.0
    Last Updated: 03/04/2011

    Details: Assuming you were hired as an Entry Level Consultant by IDA Systems to create
    a program for FIAT Automotive USA inventory. For each item of FIAT Automotive inventory
    would have: Stock Number, Make, Model, Color, Retail Price, Dealer's Invoice. At the end
    of each month, the Sales Dealer of FIAT would be able to print a report of each item.
    The data file is called "FIAT_data.txt".
*/

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <iomanip>
using std::setw;
using std::setprecision;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <fstream>
using std::ifstream;
#include "cars.h"

void readFile(vector<cars>& car);

int main(int argc, char* argv[])
{
    vector<cars> car;

    cout << std::showpoint << std::fixed;
    cout << setprecision(2);

    return 0;
}

void readFile(vector<cars>& car)
{
    string id, make, model, color, fuel, retail, invoice;

    ifstream fin;
    fin.open("FIAT_data.txt");

    while(!fin.eof())
    {
        fin >> id >> make >> model >> color >> fuel >> retail >> invoice;
        car.push_back(cars(id, make, model, color, fuel, retail, invoice));
    }

    fin.close();
}


cars.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef CARS_H
#define CARS_H

#include <string>
using std::string;

class cars
{
    public:
        cars();
        cars(string id, string make, string model, string color, string fuel, string retail, string invoice);
        ~cars();

        string getCarId();
        void setCarId(string);

        string getCarMake();
        void setCarMake(string);

        string getCarModel();
        void setCarModel(string);

        string getCarColor();
        void setCarColor(string);

        string getCarFuel();
        void setCarFuel(string);

        string getCarRetail();
        void setCarRetail(string);

        string getCarInvoice();
        void setCarInvoice(string);
    private:
        string car_id;
        string car_make;
        string car_model;
        string car_color;
        string car_fuel;
        string car_retail;
        string car_dealer_invoice;
};

#endif // CARS_H 


cars.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "cars.h"
#include <string>
using std::string;

cars::cars()
{
    car_id = 000;
    car_make = "NULL";
    car_model = "NULL";
    car_color = "NULL";
    car_fuel = "NULL";
    car_retail = 0.00;
    car_dealer_invoice = 0.00;
}

cars::cars(string id, string make, string model, string color, string fuel, string retail, string invoice)
{
    car_id = id;
    car_make = make;
    car_model = model;
    car_color = color;
    car_fuel = fuel;
    car_retail = retail;
    car_dealer_invoice = invoice;
}

cars::~cars()
{

}

string cars::getCarId()
{
    return car_id;
}
void cars::setCarId(string x)
{
    car_id = x;
}

string cars::getCarMake()
{
    return car_make;
}
void cars::setCarMake(string x)
{
    car_make = x;
}

string cars::getCarModel()
{
    return car_model;
}
void cars::setCarModel(string x)
{
    car_model = x;
}

string cars::getCarColor()
{
    return car_color;
}
void cars::setCarColor(string x)
{
    car_color = x;
}

string cars::getCarFuel()
{
    return car_fuel;
}
void cars::setCarFuel(string x)
{
    car_fuel = x;
}

string cars::getCarRetail()
{
    return car_retail;
}
void cars::setCarRetail(string x)
{
    car_retail = x;
}

string cars::getCarInvoice()
{
    return car_dealer_invoice;
}
void cars::setCarInvoice(string x)
{
    car_dealer_invoice = x;
}


Errors:

||=== CIS225_Midterm, Debug ===|
obj/Debug/main.o||In function `readFile(std::vector<cars, std::allocator<cars> >&)'
/home/packetpirate/Documents/C++ Projects/CIS225_Midterm/main.cpp|51|undefined reference to `cars::cars(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'|
/home/packetpirate/Documents/C++ Projects/CIS225_Midterm/main.cpp|51|undefined reference to `cars::~cars()'|
/home/packetpirate/Documents/C++ Projects/CIS225_Midterm/main.cpp|51|undefined reference to `cars::~cars()'|
obj/Debug/main.o||In function `std::vector<cars, std::allocator<cars> >::_M_insert_aux(__gnu_cxx::__normal_iterator<cars*, std::vector<cars, std::allocator<cars> > >, cars const&)'
/usr/include/c++/4.4/bits/vector.tcc|312|undefined reference to `cars::~cars()'|
/usr/include/c++/4.4/bits/vector.tcc|312|undefined reference to `cars::~cars()'|
obj/Debug/main.o||In function `__gnu_cxx::new_allocator<cars>::destroy(cars*)'
/usr/include/c++/4.4/ext/new_allocator.h|115|undefined reference to `cars::~cars()'|
obj/Debug/main.o:/usr/include/c++/4.4/bits/stl_construct.h|83|more undefined references to `cars::~cars()' follow|
||=== Build finished: 7 errors, 0 warnings ===|
Mar 6, 2011 at 2:31am
Sorry for the stupid question, but do you link cars.o with main.o. In fact, you have errors in cars.cpp, so you probably don't. For example you can not assign number to string, like you do in the constructor.

Regards
Mar 6, 2011 at 2:51am
Hmm... let me change that real quick. But that doesn't explain the error with the destructor. And besides, I don't think the compiler was referring to that. It said there was a problem with the constructor with the parameters.
Mar 6, 2011 at 3:03am
It says undefined reference, but it's pretty obvious that I declared the constructor and wrote out the function correctly. And if the files weren't linked, which they are, wouldn't it give me errors saying that the rest of my functions are undefined? I'm using Code::Blocks 10.05
Mar 6, 2011 at 3:08am
It said there was a problem with the constructor with the parameters.

It is not overload resolution problem (problem with matching the parameters as you say.) I know, because what you get are linker errors ("undefined reference"). Overload resolution happens during compilation, and linking is performed if compilation (and all its chores) have completed successfully. Besides, you the destructor reference is flagged too, and as you know the destructor takes no arguments.

The fact that your code had errors and the compiler didn't bark at you (the linker was launched) can only mean that the car.cpp file was not used in the build. If a source file is not compiled, it can not produce object file (.o) and the linker can not resolve "references" to functions that are defined in it. Basically, I think that your car.cpp is not registered as part of the IDE project if you use IDE, or you simply forget to compile and link it yourself if you perform the build manually (without IDE).

Regards
Last edited on Mar 6, 2011 at 3:09am
Mar 6, 2011 at 3:11am
Well the files are all in the same project and I included the header file in both CPP files... do I need to do something else to link them? I haven't done separate CPP files before... just custom header files.

Also, what errors in my code are you referring to?
Mar 6, 2011 at 3:28am
You have car_retail = 0.00; for example. I am pretty sure that this is an error. It certainly doesn't compile on my system (mingw g++). Neither does car_retail = 0; for that matter, but the latter may compile on your system depending on your library implementation, and only due to the possible implicit conversion from integer 0 to null pointer. What I am saying is this. Your car.cpp source had errors and the linker was launched still. The linker is only launched if the compiler finishes ok with all the sources. But how can the compilation be fine when one of the source files is erroneous? The only possible explanation for me is that this file was never included in the build and the other files (main.cpp) compiled ok. This explains why the linker can not link to the constructor and destructor definitions (the barks you get). It can not find the compiler result for something that was never compiled.

At least that is my theory :)
Mar 6, 2011 at 3:41am
Alright, I'll try changing that and get back to you.
Mar 6, 2011 at 5:38am
Ah, I figured it out. The problem was that when I added the file, I linked it, but I forgot to set a target for the file. It runs fine now.
Mar 6, 2011 at 5:48am
possible implicit conversion from integer 0 to null pointer

Actually, that is a valid way to set a null pointer. Though the syntax on that line is very strange...TC shouldn't be assigning numbers to a string in any of those cases.

And I have to ask, why all the getter and setter methods? Is why not just make the members public?
Mar 6, 2011 at 6:09am
Making those members public is bad practice.
Mar 6, 2011 at 6:27am
Making those members public is bad practice.


Ugh. That's a really stupid thing to say IMO. Having getters/setters is no different from having public members except you have to type a slight different line of code.
Mar 6, 2011 at 7:56am
+1 firedraco.

There's nothing wrong with public data members. This class is basically nothing more than a simple data struct, anyway, so everything might as well be public.

The "member vars must always be private" rule is absurd. Making members private is important when encapsulating, but encapsulating this particular class makes no sense.
Topic archived. No new replies allowed.