Virtual derived functions and include loops

I am currently learning C++ as a student and I have a problem.

Here is my problem :

  • I have a class Point (described below)
  • I have a class Cartesian and Polar whom inherit from Point

I need to create a function to convert a Cartesian to Polar and a Polar to Cartesian. It needs to be callable directly from Cartesian and Polar or by Point.

Here’s roughly what I got right now (it doesn’t compile) :

// point.hpp
class Point {
    public:
        virtual void display(std::ostream&) const = 0;
        virtual void convert(Cartesian&) const = 0;
        virtual void convert(Polar&) const = 0;
        friend std::ostream& operator<<(std::ostream&, const Point&);
};

// cartesian.hpp
class Cartesian : public Point {
    private:
        double _x;
        double _y;
    
    public:
        Cartesian();
        Cartesian(const double, const double);
        void display(std::ostream&) const;
        void convert(Polar&) const override;
        void setX(const double);
        void setY(const double);
        double getX() const;
        double getY() const;
};

// polar.hpp
class Polar : public Point {
    private:
        double _a;
        double _d;
    
    public:
        Polar();
        Polar(const double, const double);
        void display(std::ostream&) const;
        void convert(Cartesian&) const override;
        void setAngle(const double);
        void setDistance(const double);
        double getAngle() const;
        double getDistance() const;
};

I know the design is crap but I can’t change it.

Here’s the unit tests to pass :

TEST_CASE ( "TP1_Point::ConversionVersPolaire_V1" ) {
 const double x = 12.0;
 const double y = 24.0;
 const double a = 63.434948;
 const double d = 26.832815;

 const Cartesian c(x,y);
 Polar p;

 c.convert(p);

 REQUIRE ( p.getAngle() == Approx(a).epsilon(1e-3) );
 REQUIRE ( p.getDistance() == Approx(d).epsilon(1e-3) );
}

//----------------------------------------------------------------------------------------------- 
TEST_CASE ( "TP1_Point::ConversionVersCartesien_V1" ) {
 const double a = 12.0;
 const double d = 24.0;
 const double x = 23.475542;
 const double y = 4.9898805;

 const Polar p(a,d);
 Cartesian c;

 p.convert(c);

 REQUIRE ( c.getX() == Approx(x).epsilon(1e-3) );
 REQUIRE ( c.getY() == Approx(y).epsilon(1e-3) );
}

//----------------------------------------------------------------------------------------------- 
TEST_CASE ( "TP1_Point::ConversionVirtuel" ) {
 const double x = 12.0;
 const double y = 24.0;
 const double a = 63.434948;
 const double d = 26.832815;

 Cartesian c(x,y);
 Polar p(a,d);

 const Point * x1 = &c;
 const Point * x2 = &p;

 Cartesian c1;
 Cartesian c2;
 Polar p1;
 Polar p2;

 x1->convert(c1);
 x1->convert(p1);
 x2->convert(c2);
 x2->convert(p2);

 REQUIRE ( c1.getX() == Approx(x).epsilon(1e-3) );
 REQUIRE ( c1.getY() == Approx(y).epsilon(1e-3) );
 REQUIRE ( c2.getX() == Approx(x).epsilon(1e-3) );
 REQUIRE ( c2.getY() == Approx(y).epsilon(1e-3) );

 REQUIRE ( p1.getAngle() == Approx(a).epsilon(1e-3) );
 REQUIRE ( p1.getDistance() == Approx(d).epsilon(1e-3) );
 REQUIRE ( p2.getAngle() == Approx(a).epsilon(1e-3) );
 REQUIRE ( p2.getDistance() == Approx(d).epsilon(1e-3) );
}

Thanks in advance for your answers.

Answer

In these declarations of member functions

    virtual void convert(Cartesian&) const = 0;
    virtual void convert(Polar&) const = 0;

the names Cartesian and Polar are not yet declared.

You need either to introduce them as forward declarations before the class Point like

class Cartesian;
class Polar;

or to use elaborated type names in the function declarations like

    virtual void convert( class Cartesian& ) const = 0;
    virtual void convert( class Polar& ) const = 0;

As the function display is also virtual you should use the keyword override in its declarations in derived classes.

    void display(std::ostream&) const override;

Also if one of the function convert is not overridden in one of the derived classes then the corresponding class will be still abstract.