xavi
xavi

Reputation: 433

c++ Functions that call virtual functions inside

Have been trying to develop a better understanding of virtual functions. For the sake of argument, say I have a base class:

class Shape
{
protected:
    string _name;
    int _num;
public:
    Shape();
    virtual double CalcShape();
};

And 2 lower classes:

class Rectangle : public Shape
{
private:
    double _height;
    double _width;
public:
    Rectangle();
    Rectangle(double, double);
    double GetHeight();
    double GetWidth();
    double CalcShape(double, double); //calculates rectangle
};

class Triangle : public Shape
{
private:
    double _side1;
    double _side2;
    double _side3;
public:
    Triangle();
    Triangle(double, double, double);
    double GetSide();
    double CalcShape(double, double, double); //calculates triangle
};

Say I also have a function called ShowCalc(Shape&);. This function calls the CalcShape() function inside.

void ShowCalc(Shape& sh)
{
    return sh.CalcShape(); 
}

Now is there a way to get this function CalcShape() to accept input of both the Triangle's GetSide() function and the Rectangle's GetHeight() and GetWidth() seeing as how Triangle takes 3 parameters and Rectangle takes 2?

Upvotes: 0

Views: 279

Answers (1)

Jack
Jack

Reputation: 133577

I see multiple design errors here:

  • you can't use virtual method with references: a reference points to a real object of that specified type. Dynamic dispatch doesn't work because Shape& is a Shape and even if you assign a children class to it when initializing the value, everything that is derived is discarded because of object slicing.
  • virtual functions are meant to be used when overridden methods in subclasses have a specific implementation. An overridden method has the same signature of the original method. In your case you have CalcShape(void) in Shape and CalcShape(double, double) in Rectangle. This is not overriding, this is overloading which is a complete different thing. You can take advance of override keyword in C++11 to be sure you are correctly overriding virtual methods.
  • virtual methods should be pure if the implementation on base class makes no sense (since you can't compute the area of an unknown type shape). If you had this pure ( = 0 ) the compiler would have warned you about the fact that none of children classes are actually overriding it.

To obtain what you want you need to use the member variables in the implementation, not pass them through the call, eg:

class Shape {
  virtual double calcArea() = 0;
}

class Rectangle : public Shape {
  private: 
    double width, height;
  public:
    virtual double calcArea() override { return width*height; }
}

Shape *shape = new Rectangle(10,20);
double area = shape->calcArea();

Upvotes: 2

Related Questions