一直在努力提高对虚拟功能的理解。为了论证,我说我有一个基类:
class Shape
{
protected:
string _name;
int _num;
public:
Shape();
virtual double CalcShape();
};
还有2个下级:
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
};
假设我还有一个名为ShowCalc(Shape&);
的函数。该函数调用里面的CalcShape()
函数。
void ShowCalc(Shape& sh)
{
return sh.CalcShape();
}
现在有一种方法可以让这个函数CalcShape()
接受Triangle的GetSide()
函数和Rectangle的GetHeight()
和GetWidth()
的输入,看看Triangle如何处理3参数和矩形需要2?
答案 0 :(得分:2)
我在这里看到了多个设计错误:
virtual
方法与引用一起使用:引用指向该指定类型的实际对象。动态分派不起作用,因为Shape&
是Shape
,即使在初始化值时为其分配子类,由于object slicing,所有派生的内容也会被丢弃。virtual
函数用于在子类中的重写方法具有特定实现时使用。重写方法具有与原始方法相同的签名。在您的情况下,CalcShape(void)
中的Shape
和CalcShape(double, double)
中的Rectangle
。这不是覆盖,这是重载,这是完全不同的事情。您可以在C ++ 11中提前override
关键字,以确保正确覆盖虚拟方法。virtual
方法应该是纯粹的(因为你无法计算未知类型形状的区域)。如果你有这个纯粹的(= 0
),那么编译器就会警告你,没有一个子类实际上覆盖了它。要获得您想要的内容,您需要在实现中使用成员变量,而不是通过调用传递它们,例如:
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();