正在调用派生方法而不是Base

Derived method being called instead of Base

本文关键字:Base 方法 调用 派生      更新时间:2023-10-16

我忘记了当基类方法没有以Derived*类型的对象的this->Derived::开头时,为什么基类方法会调用派生的虚拟方法。请参阅Arc::SetAngles(…):中的注释行

摘要:

class Shape {
    public:
    //...
    protected:
    //...
    virtual void CalculateArea()=0;
    virtual void CalculateCenter()=0;
    private:
    //...
};

基础:

void Arc::CalculateArea() {
    _area = 0.5 * _radius * _radius * _theta;
}
void Arc::CalculateCenter() {
    double e = GetEndAngle();
    double s = GetStartAngle();
    double d = e - s;
    double x = 0.0;
    double y = 0.0;
    double offset = 0.0;
    if(d < 0.0) {
        offset = a2de::A2DE_PI;
    }
    x = (GetPosition().GetX() + std::cos(((s + e) / 2.0) + offset) * _radius);
    y = (GetPosition().GetY() + -std::sin(((s + e) / 2.0) + offset) * _radius);
    _center = Vector2D(x, y);
    return;
}
void Arc::SetAngles(double startAngle, double endAngle) {
    if(startAngle < 0.0) {
        startAngle += A2DE_2PI;
    }
    if(endAngle < 0.0) {
        endAngle += A2DE_2PI;
    }
    _startAngle = std::fmod(startAngle, A2DE_2PI);
    _endAngle = std::fmod(endAngle, A2DE_2PI);
    //must call base version explicitly otherwise Sector:: versions are called when object is of type Sector* regardless if prefaced with this-> or nothing.
    Arc::CalculateCenter();
    Arc::CalculateLength();
    Arc::CalculateArea();
}

衍生:

void Sector::CalculateArea() {
    _area = (_radius * _radius * _theta) / 2.0;
}
void Sector::CalculateCenter() {
    double x = (4 * _radius) / (3 * a2de::A2DE_PI);
    x += this->GetX();
    _center = Vector2D(x, GetY());
}
void Sector::SetAngles(double startAngle, double endAngle) {
    Arc::SetAngles(startAngle, endAngle);
    Sector::CalculateArea();
    Sector::CalculateCenter();
}

C++旨在为您提供以下选择:

  1. 使用非虚拟函数-基类调用使用基类方法
  2. 使用虚拟函数-基类调用使用派生类方法

你的选择,你想要哪种行为?

也就是说,在你的代码中有一些混乱&继承层次结构。

如果一个扇形IS-a弧,那么可以说(这里的几何参数,而不是OO设计参数)扇形面积和弧面积的计算应该是相同的。看看你们的代码,它们是——你们可能会去掉Sector::CalculateArea(相同公式的diff代码)。

然而,CalculateCenter方法对于这两种类型是不同的,并且基类代码不能利用派生类重写(几何参数和OO参数),这强烈表明Sector不是Arc。

您的代码可能是为了继承而继承的,在这种情况下,情况很糟糕。问问自己,正确的继承是否可能同时来自Shape

回到一个严格的几何论点,弧不是扇形:弧在圆的周长上(如果你愿意的话,是曲线),扇形是圆的一部分(饼状)。完全不同的实现可以在代码中看到这一点。