【问题标题】:Virtual derived functions and include loops虚拟派生函数和包含循环
【发布时间】:2021-11-21 08:20:44
【问题描述】:

我目前正在学习 C++,但我遇到了一个问题。

这是我的问题:

  • 我有一个班级点(如下所述)
  • 我有一个继承自 Point 的 Cartesian 和 Polar 类

我需要创建一个函数来将笛卡尔坐标转换为极坐标并将极坐标坐标转换为笛卡尔坐标。它需要直接从笛卡尔和极坐标或点调用。

这大概是我现在得到的(它不能编译):

// 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;
};

我知道设计很糟糕,但我无法改变它。

这是要通过的单元测试:

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) );
}

提前感谢您的回答。

【问题讨论】:

  • 编译器的错误信息是什么?我认为您需要在点类中进行前向声明,因为它不知道 Polar 和 Cartesian,或者您有循环包含。能否也提供包含语句?
  • 您需要覆盖两个类中的两个转换函数(其中一个将是微不足道的)。
  • 你的问题是在数学课上没见过笛卡尔和极坐标吗?然后很难对转换进行编程。 C++有三角函数可以帮助cmath中的转换
  • error: cannot declare variable ‘p’ to be of abstract type ‘Polar’ Polar p; 我使用了下面的详细类型。数学转换不是问题,是我想不通的代码结构。
  • 可能最后一个错误之后是信息性消息,说明 Polar 中的纯虚函数缺少覆盖。

标签: c++ class oop types virtual


【解决方案1】:

在这些成员函数的声明中

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

笛卡尔和极坐标的名称尚未声明。

您需要在类 Point 之前将它们作为前向声明引入

class Cartesian;
class Polar;

或在函数声明中使用详细的类型名称,如

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

由于函数 display 也是虚拟的,您应该在派生类的声明中使用关键字 override。

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

此外,如果其中一个函数 convert 没有在派生类之一中被覆盖,则相应的类仍将是抽象的。

【讨论】:

  • 我尝试了详细的类型名称,并在笛卡尔和极坐标中覆盖了convert() 函数,但它仍然无法编译:error: cannot declare variable ‘p’ to be of abstract type ‘Polar’ Polar p; 如果你这样做,就好像精心制作的类会覆盖主类明白我的意思。
  • @Jairo 你需要覆盖函数显示。也就是说,所有的纯虚函数(在基类中有 3 个纯虚函数)都应该在每个派生类中被覆盖。
  • 已经是了,我只是省略了。其他功能的所有单元测试均通过。它只是转换会带来问题。
  • @Jairo 在 Polar 类之前,您需要包含笛卡尔类的前向声明。反之亦然,在带有类定义笛卡尔的标题中,您需要包含 Polar 类的前向声明。
  • 好的,我修复了我的代码,现在它可以工作了,我使用了详细的类型名称并完成了虚拟重新定义。谢谢大家的回复。
猜你喜欢
  • 1970-01-01
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2020-09-30
  • 2015-04-16
  • 1970-01-01
  • 2013-08-25
相关资源
最近更新 更多