简体   繁体   中英

Derived method being called instead of Base

I'm forgetting why a base class method would call a derived virtual method when the method is not prefaced with this-> or Derived:: of an object of type Derived* See the commented line in Arc::SetAngles(...):

Abstract:

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

Base:

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

Derived:

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++ was designed to give you this choice:

  1. Use non-virtual function - base-class invocation uses base-class method.
  2. Use virtual function - base-class invocation uses derived-class method.

Your choice, which behavior do you want?

THAT said, there's some confusion in your code & inheritance hierarchy.

IF a Sector IS-A Arc, then arguably (geometric argument here, not OO design argument) the calculation of Sector area and Arc area should be the same. And looking at your code, they are - you might drop the Sector::CalculateArea (diff code for same formula).

HOWEVER, the requirement that the CalculateCenter method be different for the two types, and that the base-class code cannot leverage the derived class override (geometric argument AND OO argument), STRONGLY suggests that a Sector IS NOT an Arc.

You're code may be inheriting for the sake of inheriting, and in this case poorly. Ask yourself if the proper inheritance might be both from Shape .

Going back to a strictly Geometric argument, an Arc IS NOT a Sector: An arc is on the perimeter of a circle (curved line, if you will), and a sector is a portion of the circle (pie shaped). This is seen in your code by completely disparate implementations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM