Data Member Refrence Problem

I have created this program with the class Rectangle, and i have gotten most of the errors out I think. However, I am getting these errors, which I do not know how to fix. I would really appreciate anyone's help if they could tell me how to fix this. Thanks.



Undefined symbols for architecture x86_64:
"Rectangle::totalPerimeter", referenced from:
Rectangle::summary() in main.o
Rectangle::getInfo() in main.o
"Rectangle::rectanglesCreated", referenced from:
Rectangle::process() in main.o
Rectangle::summary() in main.o
"Rectangle::totalArea", referenced from:
Rectangle::summary() in main.o
Rectangle::getInfo() in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)




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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

#include <iostream>
using namespace std;



class Rectangle{
    
public:
    Rectangle();
    
    
    void displayMaxRectangles(){
        cout << "The maximum number of rectangles that can be created is " << maxRectangles << endl;
    }
    
    
    void rectangleCharacters(){
        cout << "Enter the desired border character of the rectangle." << endl;
        cin >> borderCharacter;
        cout << "Enter the desired filler character of the rectangle." << endl;
        cin >> fillCharacter;
    }
    
    
    void process(){
        do{
            getInfo();
            cout << "Would you like to display the rectangle?" << endl;
            cin >> yesno;
            while ((yesno != 'n') || (yesno != 'N')){
                if ((yesno == 'y') || (yesno == 'Y')){
                    rectangleCharacters();
                    for (int j = 0; j < length; j++){
                        if ((j == 0) || (j == length - 1)){
                            for (int v = 0; v < length; v++){
                                cout << borderCharacter;
                            }
                        }
                        else{
                            for (int w = 0; w < width; w++){
                                if ((w == 0) || (w == width - 1)){
                                    cout << borderCharacter;
                                }
                                else{
                                    cout << fillCharacter;
                                }
                            }
                        }
                    }
                }
                
            }
            cout << endl << endl;
            rectanglesCreated++;
            cout << "Would you like to create another rectangle?" << endl;
            cin >> yesno;
            if ((yesno == 'n') || (yesno == 'N')){
                summary();
            }
            
        }while(rectanglesCreated < maxRectangles);
    }
    
    
    void summary(){
        cout << endl << endl << endl;
        cout << "Rectangles Built: " << rectanglesCreated << endl;
        cout << "Average Area: " << (totalArea / rectanglesCreated) << endl;
        cout << "Average Perimeter: " << (totalPerimeter / rectanglesCreated);
    }
    
    
    void getInfo(){
        cout << "Enter the desired length of the rectangle." << endl;
        cin >> length;
        cout << "Enter the desired width of the rectangle." << endl;
        cin >> width;
        cout << "The perimeter of this rectangle is " << (length * 2) + (width * 2);
        cout << "The area of this rectangle is " << (length * width);
        totalPerimeter += (length * 2) + (width * 2);
        totalArea += length * width;
    }
    
    
    
    
private:
    double length, width;
    char borderCharacter, fillCharacter, yesno;
    static const int maxRectangles;
    static int rectanglesCreated;
    static double totalPerimeter, totalArea;
    const int MAX, MIN;
    
};

const int Rectangle::maxRectangles = 5;

Rectangle::Rectangle ():MAX(25), MIN(5){
    length = 5;
    width = 10;
    borderCharacter = '#';
    fillCharacter = '*';
}


int main(){

    Rectangle rect;
    rect.displayMaxRectangles();
    rect.process();
    rect.summary();
    
    
    return 0;
}
I seperated the code in to two files: Rectangle.h and main.cpp
Rectangle.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
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
94
95
96
97
98
99
100
101
#include <iostream>



class Rectangle {
    
public:
    Rectangle();
	void displayMaxRectangles();
	void rectangleCharacters();
	void process();
	void summary();
	void getInfo();
     
private:
    double length, width;
    char borderCharacter, fillCharacter, yesno;
    const int MAX, MIN;

};
static const int maxRectangles = 5;
static int rectanglesCreated;
static double totalPerimeter, totalArea;

void Rectangle::displayMaxRectangles(){
	std::cout << "The maximum number of rectangles that can be created is " << maxRectangles << std::endl;
}
    
    
void Rectangle::rectangleCharacters(){
     std::cout << "Enter the desired border character of the rectangle." << std::endl;
     std::cin >> borderCharacter;
     std::cout << "Enter the desired filler character of the rectangle." << std::endl;
     std::cin >> fillCharacter;
}
    
void Rectangle::process(){
     do{
        getInfo();
        std::cout << "Would you like to display the rectangle?" << std::endl;
        std::cin >> yesno;
        while ((yesno != 'n') || (yesno != 'N')){
             if ((yesno == 'y') || (yesno == 'Y')){
	              rectangleCharacters();
                  for (int j = 0; j < length; j++){
                        if ((j == 0) || (j == length - 1)){
                            for (int v = 0; v < length; v++){
                                std::cout << borderCharacter;
                            }
                        }
                        else{
                            for (int w = 0; w < width; w++){
                                if ((w == 0) || (w == width - 1)){
                                    std::cout << borderCharacter;
                                }
                                else{
                                    std::cout << fillCharacter;
                                }
                            }
                        }
                    }
                }
                
            }
            std::cout << std::endl << std::endl;
            rectanglesCreated++;
            std::cout << "Would you like to create another rectangle?" << std::endl;
            std::cin >> yesno;
            if ((yesno == 'n') || (yesno == 'N')){
                summary();
            }
            
        }while(rectanglesCreated < maxRectangles);
    }
    
    
    void Rectangle::summary(){
        std::cout << std::endl << std::endl << std::endl;
        std::cout << "Rectangles Built: " << rectanglesCreated << std::endl;
        std::cout << "Average Area: " << (totalArea / rectanglesCreated) << std::endl;
        std::cout << "Average Perimeter: " << (totalPerimeter / rectanglesCreated);
    }
    
    
    void Rectangle::getInfo(){
        std::cout << "Enter the desired length of the rectangle." << std::endl;
        std::cin >> length;
        std::cout << "Enter the desired width of the rectangle." << std::endl;
        std::cin >> width;
        std::cout << "The perimeter of this rectangle is " << (length * 2) + (width * 2);
        std::cout << "The area of this rectangle is " << (length * width);
        totalPerimeter += (length * 2) + (width * 2);
        totalArea += length * width;
    }

Rectangle::Rectangle (): MAX(25), MIN(5){
    length = 5;
    width = 10;
    borderCharacter = '#';
    fillCharacter = '*';
}


main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
#include "Rectangle.h"
using namespace std;
int main(){

    Rectangle rect;
    rect.displayMaxRectangles();
    rect.process();
    rect.summary();
    
    
    return 0;
}

I was having the same issue. Check out this source:http://stackoverflow.com/questions/17342703/how-and-where-to-define-class-variable-when-using-header-files-in-c
Last edited on
The duplicate symbols is because a static member variable needs to be declared in a header file and defined in an implementation file, i.e.

Header file:
1
2
3
4
5
6
7
8
9

// Rectangle.h
class Rectangle
{
    //...
    static int rectanglesCreated;
   //...

};


Implementation file:
1
2
3
4
5

// Rectangle.cpp
int Rectangle::rectanglesCreated = 0;

//... 



There is also another way that uses a static function and static variable within the function. ncount1 is the equivalent of rectanglesCreated in this example.

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

// Example1.hh



#ifndef example1_hh_
#define example1_hh_


class Example1
{
public:
	// Constructor and Destructors
	Example1();
	virtual ~Example1();

public:
	// Public functions
       static unsigned int GetCount1() { return ncount1; }
       static unsigned int GetCount2() { return Increment(0); }
    
private:
	// Private functions
       static unsigned int Increment(const unsigned int& incr = 1);

private:
	// Private variables
       static unsigned int ncount1;


};



//----------------------------------------------------------------------------//
inline unsigned int Example1::Increment(const unsigned int& incr)
{
    static unsigned int hidden_ncount = 0;
    return hidden_ncount += incr;
}
//----------------------------------------------------------------------------//


#endif


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

// Example1.cc


#include "Example1.hh"

//============================================================================//

unsigned int Example1::ncount1 = 0;

//============================================================================//

Example1::Example1()

{
    ++ncount1;
    Increment();
}

//============================================================================//

Example1::~Example1()
{  }

//============================================================================//


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

// main.cc

#include "Example1.hh"
#include <iostream>

void print();

int main()
{
    print();
    Example1 exe1_1;
    print();
    Example1 exe1_2;
    print();

    return 0;

}

void print()
{
    static unsigned int n = 0;
    std::cout << "\nN = " << n++ << std::endl;
    std::cout << "COUNT (via static member variable) : " << Example1::GetCount1() << std::endl;
    std::cout << "COUNT (via static hidden variable) : " << Example1::GetCount2() << std::endl;
}




N = 0
COUNT (via static member variable) : 0
COUNT (via static hidden variable) : 0

N = 1
COUNT (via static member variable) : 1
COUNT (via static hidden variable) : 1

N = 2
COUNT (via static member variable) : 2
COUNT (via static hidden variable) : 2


The advantage of the second method (using Increment and hidden_ncount instead of ncount1) is that you could easily move those constructor and destructor definitions in the implementation file to the header file and eliminate the need for an Example1 implementation file (i.e. Example1.cc in my example)
Topic archived. No new replies allowed.