派生的方法被调用而不是Base

时间:2012-07-29 08:30:23

标签: c++ polymorphism

我忘了为什么基类方法在方法没有以this->或类型为Derived::的{​​{1}} 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();
}

1 个答案:

答案 0 :(得分:2)

C ++旨在为您提供此选择:

  1. 使用非虚函数 - 基类调用使用基类方法。
  2. 使用虚函数 - 基类调用使用派生类方法。
  3. 您的选择,您想要哪种行为?

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

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

    但是,要求CalculateCenter方法对于这两种类型是不同的,并且基类代码不能利用派生类覆盖(几何参数AND OO参数),强烈建议扇区不是一个弧。

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

    回到一个严格的几何参数,一个弧不是一个扇区:一个弧在圆的周边(曲线,如果你愿意),一个扇区是圆的一部分(饼形)。这可以通过完全不同的实现在您的代码中看到。