Reputation: 537
I'm creating a class hierarchy of two dimensional shapes. The base class is a Quadrilateral, Trapezoid and Parallelogram inherit Quadrilateral, Rectangle inherits Parallelogram, and Square inherits Rectangle. I'm attempting to test my classes, so I can correct any errors I find, but I'm receiving a compiling error. This is the relevant sections pertaining to my error:
Shapes.h:
#ifndef Shapes_h
#define Shapes_h
class Point {
public:
Point();
Point(int, int);
int getX();
int getY();
void setValues();
private:
int x;
int y;
};
class Quadrilateral {
public:
Quadrilateral();
Quadrilateral(Point, Point, Point, Point);
void print();
private:
Point point1;
Point point2;
Point point3;
Point point4;
};
class Parallelogram : public Quadrilateral {
public:
Parallelogram();
Parallelogram(Point, Point, int);
void print();
private:
Point point1;
Point point2;
Point point3;
Point point4;
};
class Trapezoid : public Quadrilateral {
public:
Trapezoid();
Trapezoid(Point, Point, int, int);
void print();
private:
Point point1;
Point point2;
Point point3;
Point point4;
};
class Rectangle : public Parallelogram {
public:
Rectangle();
Rectangle(Point, int, int);
void print();
private:
Point point1;
Point point2;
Point point3;
Point point4;
};
class Square : public Rectangle {
public:
Square();
Square(Point, int);
void print();
private:
Point point1;
Point point2;
Point point3;
Point point4;
};
#endif /* Shapes_h */
Point.cpp:
#include "Shapes.h"
#include <iostream>
using namespace std;
Point::Point() {
this->x = 0;
this->y = 0;
}
Point::Point(int x, int y){
this->x = x;
this->y = y;
}
int Point::getX(){
return this->x;
}
int Point::getY(){
return this->y;
}
Square.cpp:
#include "Shapes.h"
#include <iostream>
using namespace std;
Square::Square(Point a, int len):Rectangle(a, len, len) {
}
Rectangle.cpp (File giving me the error):
#include "Shapes.h"
#include <iostream>
using namespace std;
Rectangle::Rectangle(Point a, int len, int height):Parallelogram(a, Point(a.getX(), a.getY()+height), len) {
}
Parallelogram.cpp:
#include "Shapes.h"
#include <iostream>
using namespace std;
Parallelogram::Parallelogram(Point a, Point b, int len):Quadrilateral(a, b, Point(a.getX()+len,a.getY()), Point(b.getX()+len, b.getY())) {
}
Quadrilateral.cpp:
#include "Shapes.h"
#include <iostream>
using namespace std;
Quadrilateral::Quadrilateral(){
this->point1 = Point(0,0);
this->point2 = Point(0,1);
this->point3 = Point(1,0);
this->point4 = Point(1,1);
}
Quadrilateral::Quadrilateral(Point a, Point b, Point c, Point d) {
this->point1 = a;
this->point2 = b;
this->point3 = c;
this->point4 = d;
}
Test Driver:
#include "Shapes.h"
#include <iostream>
using namespace std;
int main() {
Square square = Square(Point(1,1),2);
square.print();
return 0;
}
Command Line Compile Error:
g++ -Wall -Wextra -c *.cpp
g++ -o *.o
/usr/bin/ld: Rectangle.o: in function `Rectangle::Rectangle(Point, int, int)':
Rectangle.cpp:(.text+0x74): undefined reference to `Parallelogram::Parallelogram(Point, Point, int)'
collect2: error: ld returned 1 exit status
So, as far as I can tell, Square is successfully able to call the Rectangle constructor, but Rectangle is failing to call Parallelogram.
Upvotes: 0
Views: 310
Reputation: 537
The issue here was with the compiling command given. The -o
flag allows you to name the outputted executable. Because you didn't prove a name, it is taking the first file provided in *.o
and overwriting it, using it as the file name. Because it was overwritten, it breaks the compilation of the other files. The solution here would be to provide a name or remove the -o
flag.
Upvotes: 0
Reputation: 489
You can improve your code by:
class Point
Point.hpp
#ifndef Point_h
#define Point_h
namespace Shape {
class Point {
public:
Point();
Point(int x, int y);
int getX();
int getY();
std::string toString();
private:
int x;
int y;
};
}
#endif /* Point_h */
Point.cpp
#include <Point>
#include <iostream>
#include <sstream>
#include <string>
namespace Shape {
Point::Point() {
this -> x = 0;
this -> y = 0;
}
Point::Point(int x, int y) {
this -> x = x;
this -> y = y;
}
int Point::getX() {
return this -> x;
}
int Point::getY() {
return this -> y;
}
std::string Point::toString() {
std::ostringstream oss;
oss << "Point(";
oss << x;
oss << ", ";
oss << y;
oss << ")";
return oss.str();
}
}
Quadrilateral.hpp
#ifndef Quadrilateral_h
#define Quadrilateral_h
namespace Shape {
class Quadrilateral {
public:
Quadrilateral();
Quadrilateral(Point a, Point b, Point c, Point d);
void print();
protected:
Point point1;
Point point2;
Point point3;
Point point4;
};
}
#endif /* Quadrilateral_h */
Quadrilateral.cpp
#include <Quadrilateral>
#include <iostream>
namespace Shape {
Quadrilateral::Quadrilateral() {
this -> point1 = Point(0, 0);
this -> point2 = Point(0, 1);
this -> point3 = Point(1, 0);
this -> point4 = Point(1, 1);
}
Quadrilateral::Quadrilateral(Point a, Point b, Point c, Point d) {
this -> point1 = a;
this -> point2 = b;
this -> point3 = c;
this -> point4 = d;
}
void Quadrilateral::print() {
std::cout<<"Quadrilateral: "<<point1.toString()<<", "<<point2.toString()<<", "<<point3.toString()<<", "<<point4.toString()<<std::endl;
}
}
Parallelogram.hpp
#ifndef Parallelogram_h
#define Parallelogram_h
#include <Quadrilateral>
#include <iostream>
namespace Shape {
class Parallelogram: public Quadrilateral {
public:
Parallelogram() = delete;
Parallelogram(Point a, Point b, int len);
void print();
};
}
#endif /* Parallelogram_h */
Parallelogram.cpp
#include <Parallelogram>
#include <iostream>
namespace Shape {
Parallelogram::Parallelogram(Point a, Point b, int len): Quadrilateral(a, b, Point(a.getX() + len, a.getY()), Point(b.getX() + len, b.getY())) {}
void Parallelogram::print() {
std::cout<<"Parallelogram: "<<point1.toString()<<", "<<point2.toString()<<", "<<point3.toString()<<", "<<point4.toString()<<std::endl;
}
}
Trapezoid.hpp
#ifndef Trapezoid_h
#define Trapezoid_h
#include <Quadrilateral>
#include <iostream>
namespace Shape {
class Trapezoid: public Quadrilateral {
public:
Trapezoid() = delete;
Trapezoid(Point a, Point b, int len1, int len2);
void print();
};
}
#endif /* Trapezoid_h*/
Trapezoid.cpp
#include <Trapezoid>
#include <iostream>
namespace Shape {
Trapezoid::Trapezoid(Point a, Point b, int len1, int len2): Quadrilateral(a, Point(a.getX(), a.getY()+len1), b, Point(b.getX(), b.getY()+len2)) {}
void Trapezoid::print() {
std::cout<<"Trapezoid: "<<point1.toString()<<", "<<point2.toString()<<", "<<point3.toString()<<", "<<point4.toString()<<std::endl;
}
}
Rectangle.hpp
#ifndef Rectangle_h
#define Rectangle_h
#include <Parallelogram>
namespace Shape {
class Rectangle: public Parallelogram {
public:
Rectangle() = delete;
Rectangle(Point a, int len, int height);
void print();
};
}
#endif /* Rectangle_h*/
Rectangle.cpp
#include <Rectangle>
#include <iostream>
namespace Shape {
Rectangle::Rectangle(Point a, int len, int height): Parallelogram(a, Point(a.getX(), a.getY() + height), len) {}
void Rectangle::print() {
std::cout<<"Rectangle: "<<point1.toString()<<", "<<point2.toString()<<", "<<point3.toString()<<", "<<point4.toString()<<std::endl;
}
}
Square.hpp
#ifndef Square_h
#define Square_h
#include <Rectangle>
namespace Shape {
class Square: public Rectangle {
public:
Square() = delete;
Square(Point a, int len);
void print();
};
}
#endif /* Square_h*/
Square.cpp
#include <Square>
#include <iostream>
namespace Shape {
Square::Square(Point a, int len): Rectangle(a, len, len) {}
void Square::print() {
std::cout<<"Square: "<<point1.toString()<<", "<<point2.toString()<<", "<<point3.toString()<<", "<<point4.toString()<<std::endl;
}
}
main.cpp
#include <Square>
#include <Trapezoid>
int main()
{
auto square1 = Shape::Square(Point(1,1),2);
square1.print();
auto trapezoid1 = Shape::Trapezoid(Point(1,1), Point(2,0), 3, 5);
trapezoid1.print();
return 0;
}
Output will be:
Square: Point(1, 1), Point(1, 3), Point(3, 1), Point(3, 3)
Trapezoid: Point(1, 1), Point(1, 4), Point(2, 0), Point(2, 5)
Upvotes: 1