Linker error [undefined reference to ..]

May 18, 2012 at 5:46pm
Hello, this is the first time i post on this forum. I am a beginner in C++. I wrote some code in three files (sales.h, saless.cpp and main.cpp) and when i compile the project (I USE DEVC++ compiler in windows 7 32bit) i get the following errors :

[Linker error] undefined reference to `SALES::setSales(SALES::Sales&, double const*, int)'
[Linker error] undefined reference to `SALES::setSales(SALES::Sales&, double const*, int)'
[Linker error] undefined reference to `SALES::setSales(SALES::Sales&, double const*, int)'
[Linker error] undefined reference to `SALES::setSales(SALES::Sales&, double const*, int)'
ld returned 1 exit status


Here follows my code:

sales.h:

#ifndef SALES_H
#define SALES_H

namespace SALES
{
const int QUARTERS = 4;

struct Sales
{
double sales[QUARTERS];
double average;
double max;
double min;
};

void setSales(Sales & s,const double ar[], int n);

void setSales(Sales & s);

void showSales(const Sales & s);

}

#endif

saless.cpp:

#include <iostream>
#include "sales.h"

using namespace SALES;

void setSales(Sales & s,const double ar[], int n)
{
s.average = 0;
s.max = 0;
s.min = 0;
double sum = 0;

while(s.sales)
{
for(int i=0;i<n;i++)
{s.sales[i] = ar[i];

if(s.sales[i] > s.max)
s.max = s.sales[i];

if(s.sales[i] < s.min)
s.min = s.sales[i];

sum += s.sales[i];
}

}

s.average = sum/n;
}


void setSales(Sales & s)
{
s.average = 0;
s.max = 0;
s.min = 0;
double sum = 0;

std::cout << "Please enter the values of sales for each quarter below\n\n";

for(int i=0;i<4;i++)
{ std::cout << "Quarter #" << i+1 << ": ";
std::cin >> s.sales[i];
std::cout << "\n";

if(s.sales[i] > s.max)
s.max = s.sales[i];

if(s.sales[i] < s.min)
s.min = s.sales[i];

sum += s.sales[i];
}

s.average = sum/4;

};

void showSales(const Sales & s)
{
int size = sizeof(s.sales)/sizeof(double);
for(int i=0;i<size;i++)
{
std::cout << s.sales[i] << "\t";
}

std::cout << "\n Max: " << s.max;
std::cout << "\n Min: " << s.min;
std::cout << "\n Average : " << s.average;
};


main.cpp:

#include <cstdlib>
#include <iostream>
#include "sales.h"


//using namespace sales;

int main()
{

SALES::Sales win;
SALES::Sales mac;

//decalring size of ar[]
int n;
std::cout << "Enter the number of quarters you wish to insert (<=4 OR >0): ";
std::cin >> n;
while(n<=0 || n>4)
{std::cout << "You entered invalid value, please try again!";
std::cin >> n;
}


//constructing ar[]
double ar[n];
std::cout << "Enter the number of sales for each quarter: ";
for(int k=0;k<n;k++)
{std::cout << "\nQuarter #" << k+1 << ": ";
std::cin >> ar[k];
}

//const double sal[n] = ;

//calling functions from saless.cpp
SALES::setSales(win,ar,n);

SALES::setSales(mac);

SALES::showSales(win);
SALES::showSales(mac);

cin.get();
cin.get();

return 0;
}


Thank you for any suggestions!! I just can't find out why I get this error...help :)
May 18, 2012 at 6:53pm
1
2
3
4
5
6
7
8
9
10
11
SALES::Sales win;
SALES::Sales mac;

//[...]

SALES::setSales(win,ar,n);

SALES::setSales(mac);

SALES::showSales(win);
SALES::showSales(mac);


"::" is for defining a function that is declared inside a class (the class SALES, in this case). I don't know where did you get it from, but just get rid off it, and it should be fine ;) You just need to #include the header file of your function's declaration (as you already have) and call it simply this way:

1
2
3
4
5
6
7
8
9
10
11
Sales win;
Sales mac;

//[...]

setSales(win,ar,n);

setSales(mac);

showSales(win);
showSales(mac);


In further questions, I suggest you to put your code in "source code" format, then it's a lot easier other people to help!
Last edited on May 18, 2012 at 7:33pm
May 18, 2012 at 7:01pm
@JCaselles - wouldn't you use the scope operator (::) also with namespaces. If he wants to use any namespace within his function he can use the scope operator to use such functions i thought, just like std::cout. I may be wrong though.

@murdok - you are linking only the .cpp files right?
May 18, 2012 at 7:11pm
You need to define the functions setSales within the namespace SALES. Simply declaring using namespace SALES at the top of the file isn't enough.

saless.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
#include <iostream>
#include "sales.h"

using namespace SALES
{
    void setSales(Sales & s,const double ar[], int n)
    {
        s.average = 0;
        s.max = 0;
        s.min = 0;
        double sum = 0;

        while(s.sales)
        {
            for(int i=0;i<n;i++)
            {   s.sales[i] = ar[i];

                if(s.sales[i] > s.max)
                    s.max = s.sales[i];

                if(s.sales[i] < s.min)
                    s.min = s.sales[i];

                sum += s.sales[i];
            }
        }

        s.average = sum/n;
    }

    void setSales(Sales & s)
    {
        s.average = 0;
        s.max = 0;
        s.min = 0;
        double sum = 0;

        std::cout << "Please enter the values of sales for each quarter below\n\n";

        for(int i=0;i<4;i++)
        {  std::cout << "Quarter #" << i+1 << ": ";
            std::cin >> s.sales[i];
            std::cout << "\n";

            if(s.sales[i] > s.max)
                s.max = s.sales[i];

            if(s.sales[i] < s.min)
                s.min = s.sales[i];

            sum += s.sales[i];
        }

        s.average = sum/4;
    }

    void showSales(const Sales & s)
    {
        int size = sizeof(s.sales)/sizeof(double);
        for(int i=0;i<size;i++)
        {
            std::cout << s.sales[i] << "\t";
        }

        std::cout << "\n Max: " << s.max;
        std::cout << "\n Min: " << s.min;
        std::cout << "\n Average : " << s.average;
    }
}
May 18, 2012 at 7:19pm
@JCaselles - wouldn't you use the scope operator (::) also with namespaces. If he wants to use any namespace within his function he can use the scope operator to use such functions i thought, just like std::cout. I may be wrong though.


My bad! I didn't realize he's using namespaces! You're right. (Again, next time, you better post your code in it's dedicated format!!! ¬¬ ;)

Now, your problem is sales.cpp. This is the definition file of namespace SALES, therefore you shouldn't "use namespace SALES" but rather still define SALES, since in the header file you've only declared it, like all the functions and variables.

With only this change it should compile (compiles on mine). You have some kind of endless loop, though...

sales.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
#include <iostream>
#include "sales.h"

namespace SALES{

void setSales(Sales & s,const double ar[], int n)
{
s.average = 0;
s.max = 0;
s.min = 0;
double sum = 0;

while(s.sales)
{
for(int i=0;i<n;i++)
{s.sales[i] = ar[i];

if(s.sales[i] > s.max)
s.max = s.sales[i];

if(s.sales[i] < s.min)
s.min = s.sales[i];

sum += s.sales[i];
}

}

s.average = sum/n;
}


void setSales(Sales & s)
{
s.average = 0;
s.max = 0;
s.min = 0;
double sum = 0;

std::cout << "Please enter the values of sales for each quarter below\n\n";

for(int i=0;i<4;i++)
{ std::cout << "Quarter #" << i+1 << ": ";
std::cin >> s.sales[i];
std::cout << "\n";

if(s.sales[i] > s.max)
s.max = s.sales[i];

if(s.sales[i] < s.min)
s.min = s.sales[i];

sum += s.sales[i];
}

s.average = sum/4;

};

void showSales(const Sales & s)
{
int size = sizeof(s.sales)/sizeof(double);
for(int i=0;i<size;i++)
{
std::cout << s.sales[i] << "\t";
}

std::cout << "\n Max: " << s.max;
std::cout << "\n Min: " << s.min;
std::cout << "\n Average : " << s.average;
};
}
Last edited on May 18, 2012 at 7:20pm
May 18, 2012 at 7:27pm
Sorry, perhaps I'm a little sleepy... How the hell is this compiling?? (it does compile in code::blocks!!)

1
2
//constructing ar[]
double ar[n];


Did I miss something (again)??? shouldn't it be double * ar = new double [n];

BTW, this loop looks pretty ugly...:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(s.sales)
{
for(int i=0;i<n;i++)
{s.sales[i] = ar[i];

if(s.sales[i] > s.max)
s.max = s.sales[i];

if(s.sales[i] < s.min)
s.min = s.sales[i];

sum += s.sales[i];
}
} 

why do you even need it? you already have de for loop... (Deleting it solves the endless loop )
Last edited on May 18, 2012 at 7:33pm
May 18, 2012 at 8:09pm
Thanks JCaselles, it worked!!
May 18, 2012 at 9:55pm
How the hell is this compiling?? (it does compile in code::blocks!!)
1
2
//constructing ar[]
double ar[n];

See: http://www.cplusplus.com/forum/unices/56833/#msg306366
Last edited on May 18, 2012 at 9:58pm
May 18, 2012 at 10:21pm
An alternative, in sales.cpp, without reopening the namespace:

1
2
3
4
5
6
7
8
9
void SALES::setSales(Sales & s,const double ar[], int n)
{
     // ...
}

void SALES::setSales(Sales & s)
{
     // ...
}


May 19, 2012 at 9:03am
How the hell is this compiling?? (it does compile in code::blocks!!)
1
2
//constructing ar[]
double ar[n];


See: http://www.cplusplus.com/forum/unices/56833/#msg306366


Thanks man. Though, I still don't find the sense to that... Will it manage the dynamic memory well, like a vector, or you're just writing crappy code?
Last edited on May 19, 2012 at 9:12am
Topic archived. No new replies allowed.