Undefined Reference in virtual functions and inheritance classes

I am having difficulties with compiling the these two programs together. I get no errors when compiling the function file and the main into .o object files but when compiling together I get undefined reference to the constructors and functions. Why is this, what am I missing? Thanks!
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
#ifndef SHAPE_H
#define SHAPE_H

#include <iostream>
#include <string>

using namespace std;

const double PI = 3.14159265359;
//Base Class---------------------------------------------
class Shape {
    protected:
        //Dimensions
        double d1;
        double d2;
        int NumberDimensions;
    public:
        //Default Constructor
        Shape();
        //regular constructor
        Shape( double d );
        //Destructor
        ~Shape();
        //setters / getters
        double get_d1() { return d1; }
        double get_d2() { return d2; }
        double get_NumberDimensions() { return NumberDimensions; }
        void set_d1(double x) { d1 = x; }
        void set_d2(double x) { d2 = x; }
        //virtual function
        virtual double getArea();
        virtual string getName();
        virtual double getVolume();
};
//Shape Type-----------------------------------------------
class TwoDimensionalShape : public Shape { 
    public:
        TwoDimensionalShape();
};

class ThreeDimensionalshape : public Shape {
    protected:
        double d3;
    public:
        ThreeDimensionalshape();
        double get_d3() { return d3; }
        void set_d3(double x) { d3 = x; }   
};
//two dimensionals Shape classes-------------------------
class Circle : public TwoDimensionalShape {
    public:
        Circle(); //default constructor
        Circle( double r); //regular constructor
        double getArea(); //get area function
        string getName(); //get name of shape
};
class Square : public TwoDimensionalShape {
    public:
        Square();
        Square(double dim);
        virtual double getArea();
        virtual string getName(); 
};
class Triangle : public TwoDimensionalShape {
    public:
        Triangle();
        Triangle(double dim, double dim2); 
        virtual double getArea();
        virtual string getName(); 
};
//three dimensional shape classes-------------------------
class Sphere : public ThreeDimensionalshape {
    public:
        Sphere();
        Sphere(double dim);
        virtual double getArea();
        virtual double getVolume();
        virtual string getName();
};
class Cube : public ThreeDimensionalshape{
    public:
        Cube();
        Cube(double dim);
        virtual double getArea();
        virtual double getVolume();
        virtual string getName();   
};
class Tetrahedron : public ThreeDimensionalshape{
    public:
        Tetrahedron();
        Tetrahedron(double dim);
        virtual double getArea();
        virtual double getVolume();
        virtual string getName();
};



  #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
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <iostream>
#include <string>
#include <cmath>

#include "shape.h" //header file

using namespace std;
//----------------------------------------------
//Default constructor
Shape::Shape() { 
	d1 = 0;
	d2 = 0;
}

//Two dimensional shapes-----------------------------------
/*TwoDimensionalShape::TwoDimensionalShape() {
	NumberDimensions = 2 ;
 }*/
//Default constructor--------------------
Circle::Circle() { 
	d1 = 1;
	NumberDimensions = 2;
}
//Regular constructor--------------------
Circle::Circle( double r ) {
	d1 = r;
	NumberDimensions = 2;
}
//--
double Circle::getArea() {
	return PI * pow( d1, 2 );
}
//--
std::string Circle::getName() {
	return string("Circle");
}
//Default constructor--------------------
Square::Square() {
	d1 = 1 ;
	d2 = 1;
	NumberDimensions = 2;
}
//Regular constructor--------------------
Square::Square( double dim ) {
	d1 = dim;
	d2 = dim;
	NumberDimensions = 2;
}
//--
double Square::getArea() {
	return pow( d1, 2 );
}
//--
std::string Square::getName() {
	return string("Square");
}
//Default constructor--------------------
Triangle::Triangle() {
	d1 = 1;
	d2 = 1;
	NumberDimensions = 2;
}
//Regular constructor--------------------
Triangle::Triangle(double dim, double dim2) {
	d1 = dim;
	d2 = dim2;
	NumberDimensions = 2;
}
//--
double Triangle::getArea() {
	return (d1 * d2) / 2;
}
//--
std::string Triangle::getName() {
	return string("Triangle");
}
//Three dimensional shapes-----------------------------------
/*ThreeDimensionalshape::ThreeDimensionalshape() { 
	NumberDimensions = 3 ;
}*/
//Default constructor---------------------
Sphere::Sphere() {
	d1 = 1;
	d2 = 1;
	d3 = 1;
	NumberDimensions = 2;
}
//Regular constructor---------------------
Sphere::Sphere(double dim) {
	d1 = dim;
	d2 = dim;
	d3 = dim;
	NumberDimensions = 2;
}
//--
double Sphere::getArea(){
	return 4 * PI * pow( d1, 2 );
}
//--
double Sphere::getVolume(){
	return (4/3) * PI * pow( d1, 3 );
}
//--
std::string Sphere::getName() {
	return string("Sphere");
}
//Default constructor---------------------
Cube::Cube(){
	d1 = 1;
	d2 = 1;
	d3 = 1;
	NumberDimensions = 2;
}
//Regular constructor---------------------
Cube::Cube(double dim){
	d1 = dim;
	d2 = dim;
	d3 = dim;
	NumberDimensions = 2;
}
//--
double Cube::getArea(){
	return pow( d1, 2 );
}
//--
double Cube::getVolume(){
	return pow( d1, 3 );
}
//--
std::string Cube::getName() {
	return string("Cube");
}
//Default constructor---------------------
Tetrahedron::Tetrahedron(){
	d1 = 1;
	d2 = 1;
	d3 = 1;
	NumberDimensions = 2;
}
//Regular constructor---------------------
Tetrahedron::Tetrahedron(double dim){
	d1 = dim;
	d2 = dim;
	d3 = dim;
	NumberDimensions = 2;
}
//--
double Tetrahedron::getArea(){
	return sqrt(3) * pow( d1, 2);
}
//--
double Tetrahedron::getVolume(){
	return pow(d1, 3) / (6 * sqrt(2));
}
//--
std::string Tetrahedron::getName() {
	return string("Tetrahedron");
}


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
#include "shape.h" //header file

using namespace std;

int main() {
//Pointer Array--------------------------------------------
	Shape* arr[6];     //Assign Shape Dimensions and to Array
	Circle cir(2);     //declares value for circle ~ cir is var name
		arr[0] = &cir; //assigns cir var to array position 0
	Square sqr(3);
		arr[1] = &sqr;
	Triangle tri(4, 2);
		arr[2] = &tri;	
	Sphere sph(5);
		arr[3] = &sph;
	Cube cb(6);
		arr[4] = &cb;
	Tetrahedron trhd(7);
		arr[5] = &trhd;
//Loop each index of array and perform calculation
	for (int i = 0; i < 6; ++i) {
		cout << "\n Shape Name: \n" << arr[i]->getName() 
			 << " with area = " << arr[i]->getArea();
			 if ( arr[i]->get_NumberDimensions() == 3 )
			 {
			 	cout <<"\n with volume = " << arr[i]->getVolume();
			 }
	}
}
Last edited on
> I get undefined reference to the constructors and functions.
> Why is this, what am I missing?
http://www.cplusplus.com/forum/general/113904/#msg622050
You never defined those functions.

undefined reference to `Shape::getArea()'
undefined reference to `Shape::getName()'
undefined reference to `Shape::getVolume()'
undefined reference to `Shape::~Shape()'
undefined reference to `ThreeDimensionalshape::ThreeDimensionalshape()'
undefined reference to `TwoDimensionalShape::TwoDimensionalShape()'
get{Area,Name,Volume}() are virtual functions. If you do not intend to provide them a body, mark them as pure virtual
virtual double getArea() = 0;

you never defined the destructor for Shape. An empty one may suffice. Given that you've got virtual member functions, you ougth to mark the destructor as virtual too.
virtual ~Shape() = default;

You didn't provide a definition for the constructor of {Three,Two}DimensionalShape, ¿how the hell do you expect that to work?
Last edited on
So now declaring the virtuals as pure I get another error stating abstract type. Also how should I provide a constructor for TwoDimensionalShape and ThreeDimensionalShape? Isn't TwoDimensionalShape(); the default constructor?

~ Thanks

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
main.cpp:13:9: error: cannot declare variable ‘cir’ to be of abstract type ‘Circle’
  Circle cir(2);     //declares value for circle ~ cir is var name
         ^
In file included from main.cpp:6:0:
shape.h:55:7: note:   because the following virtual functions are pure within ‘Circle’:
 class Circle : public TwoDimensionalShape {
       ^
shape.h:38:18: note: 	virtual double Shape::getVolume()
   virtual double getVolume() = 0;
                  ^
main.cpp:15:9: error: cannot declare variable ‘sqr’ to be of abstract type ‘Square’
  Square sqr(3);
         ^
In file included from main.cpp:6:0:
shape.h:62:7: note:   because the following virtual functions are pure within ‘Square’:
 class Square : public TwoDimensionalShape {
       ^
shape.h:38:18: note: 	virtual double Shape::getVolume()
   virtual double getVolume() = 0;
                  ^
main.cpp:17:11: error: cannot declare variable ‘tri’ to be of abstract type ‘Triangle’
  Triangle tri(4, 2);
           ^
In file included from main.cpp:6:0:
shape.h:69:7: note:   because the following virtual functions are pure within ‘Triangle’:
 class Triangle : public TwoDimensionalShape {
       ^
shape.h:38:18: note: 	virtual double Shape::getVolume()
   virtual double getVolume() = 0;
> Isn't TwoDimensionalShape(); the default constructor?
If you don't declare any constructors, the compiler will provide default constructor for you.
If you declare a constructor that takes no parameters (e.g., TwoDimensionalShape();) then you need to provide a definition.
If the default behaviour was good enough for you, then you can mark it as such
1
2
3
4
class TwoDimensionalShape : public Shape { 
    public:
        TwoDimensionalShape() = default;
};


> error: cannot declare variable ‘cir’ to be of abstract type ‘Circle’
> because the following virtual functions are pure within ‘Circle’:
> virtual double getVolume() = 0;
you never defined how the volume of a circle/sqare/triangle should be computed.
1
2
3
4
5
6
7
class TwoDimensionalShape : public Shape { 
    public:
        TwoDimensionalShape() = default;
        virtual double getVolume() override{
           return 0;
        }
};
Topic archived. No new replies allowed.