Casey
Casey

Reputation: 10936

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

Upvotes: 0

Views: 143

Answers (1)

Richard Sitze
Richard Sitze

Reputation: 8463

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.

Upvotes: 2

Related Questions