### Virtual methods in inheritance classes.

I have a class Quadrilateral that is made using aggregation of 4 Points (class). From Quadrilateral I have to create an inheritance chain of several other shapes. The first one in this chain is Trapezoid.
 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103`` ``````// #ifndef POINT_H_INCLUDED #define POINT_H_INCLUDED #include "Equals.h" #include #include using namespace std; class Point { friend ostream &operator << (ostream &out, const Point &p ); friend istream &operator >> (istream &in, Point &p ); protected: double _x, _y; // coordinates public: static const double INFINITE; Point(); Point( double x, double y ); Point ( Point& P); void SetAll( double x, double y ); void SetDefault(); double getX(); double getY(); double Distance( Point &P); double Slope( Point const &P) const; void operator =(Point &P); }; #endif const double Point::INFINITE = pow(10.0,100.0); ostream &operator << (ostream &out, const Point &p ) { out << "( " << p._x << ", " << p._y << " )" << flush; return out; } // extract from format ( x, y ) istream &operator >> (istream &in, Point &p ) { char d; in >> d >> p._x >> d >> p._y >> d; return in; } Point::Point() { _x = _y = 0.0; } Point::Point( double x, double y ) { _x = x; _y = y; } Point::Point( Point &P) { *this = P; } void Point::SetAll( double x, double y ) { _x = x; _y = y; return; } void Point::SetDefault() { _x = _y = 0.0; } double Point::getX() { return _x; } double Point::getY() { return _y; } double Point::Distance( Point &P) { return sqrt( pow((_x - P._x), 2) + pow((_y - P._y), 2) ); } double Point::Slope(Point const &P) const { double slope; if ( isEqual( (_y - P._y), 0) ) // 0 in the numerator case { slope = 0.0; } if ( isEqual( (_x - P._x), 0) ) // 0 in the denominator case { slope = INFINITE; } else { slope = (_y - P._y)/(_x - P._x); } return slope; } void Point::operator=( Point &P) { _x = P._x; _y = P._y; }``````

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596`` ``````//Quadrilateral.h #ifndef QUADRILATERAL_H_INCLUDED #define QUADRILATERAL_H_INCLUDED #include "Point.h" #include using namespace std; class Quadrilateral : public Point { protected: virtual void print(ostream &out, Point& a, Point& b, Point& c, Point& d); Point A; Point B; Point C; Point D; public: Quadrilateral(); Quadrilateral(Point a, Point b, Point c, Point d ); Quadrilateral(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); void setAll(Point a, Point b, Point c, Point d); double Perimeter(); double Area(); virtual void print(ostream &out, Quadrilateral &Q ); friend ostream & operator <<(ostream &out, Quadrilateral &Q); }; #endif #include "Quadrilateral.h" #include Quadrilateral::Quadrilateral() : A(), B() , C(), D() { A.SetAll(0.0,0.0 ); B.SetAll(6.0, -2.0); C.SetAll(4.0, 8.0); D.SetAll(1.0, 5.0); } Quadrilateral::Quadrilateral(Point a, Point b, Point c, Point d ): A(a), B(b), C(c), D(d) //Normal constructor using Points { if(a.getX() >= b.getX() || a.getY() >= d.getY() || d.getX() >= c.getX() || b.getY() >= c.getY() ) //if coordinates are illegal, { //set to default values cout << "\nIllegal Quadrilateral: "<

 ``1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253`` ``````#ifndef TRAPEZIOD_H #define TRAPEZIOD_H #include "Quadrilateral.h" class Trapezoid : public Quadrilateral { protected: virtual void print(ostream &out); public: Trapezoid(); Trapezoid (Point a, Point b, Point c, Point d); double Area(); friend ostream & operator <<(ostream &out, Trapezoid &T); }; #endif #include "trapezoid.h" Trapezoid::Trapezoid() : Quadrilateral() { Point a(0.0, 0.0), b(4.0, 0.0), c(3.0, 2.0), d(1.0, 2.0); Quadrilateral::setAll(a, b, c, d); } Trapezoid::Trapezoid (Point a, Point b, Point c, Point d) : Quadrilateral(a,b,c,d) { if(isEqual( a.Slope(b), c.Slope(d) ) ) { Quadrilateral::setAll(a, b, c, d); } else { Point a1(0.0, 0.0), b1(4.0, 0.0), c1(3.0, 2.0), d1(1.0, 2.0); cout<<"Illegal Trapezoid: "<(T)<(T)); return out; } void print(ostream &out) { out<<"I'm a Trapezoid: "; //Quadrilateral::print(out); }``````

I have to make the Area and operator<< methods virtual and use a Quadrilateral pointer to point to the different shapes and return the area and print each shape and whatnot. With what I have now I get an "undefined reference to vtable" error in the constructors and I'm kinda stuck. Any ideas?
Last edited on

so probably you forgot to implement a not pure virtual member function.

It seems that the error message is not really helpful, so check all the functions to see if they are defined.
The `print`'s on line 93 (of Quadritateral) and on line 49 (of Trapezoid) need to be for each of their classes, else the vtables they are used in cannot be created.

`void Quadrilateral::print(ostream &out, Point& a, Point& b, Point& c, Point& d) `

`void Trapezoid::print(ostream &out)`

Also you will need to have:

 ``1234`` ``````void Quadrilateral::print(ostream &out, Quadrilateral &Q ) { out <<"I'm a Quadrilateral: " << Q << flush; }``````

vtables contain pointers to methods that are virtual. Each instance of a class with any virtual methods will have one as its first entry, and will be dereferenced in calls to virtual methods at runtime.