将基类的对象传递给派生类的引用函数
Posted
技术标签:
【中文标题】将基类的对象传递给派生类的引用函数【英文标题】:Passing object of base class to function of reference to derived class 【发布时间】:2020-10-08 15:41:19 【问题描述】:我正在尝试编写可以找到许多不同类型形状之间距离的代码。我已经定义了一个基类Shape
和一个virtual distance(Shape& otherShape)
函数来查找到另一个形状的距离,然后想为我的所有派生类定义它。
问题是有很多可能的形状对,所以我的解决方案是在类之外定义一组距离函数(圆-圆、圆-正方形、正方形-三等),然后调用相应的一是距离函数。我在下面添加了一个迷你示例,其中只有一个派生类 Circle
来演示问题。
当我尝试调用我的特定 circleCircleDistance
函数时,我收到一个错误,因为它无法将基类转换为派生类。有什么办法可以解决这个问题,或者我的设计是否行不通?
enum ShapeTypeCIRCLE, SQUARE;
class Shape
public:
ShapeType type;
virtual double distance(Shape& otherShape) = 0;
;
class Circle : public Shape
public:
ShapeType type = CIRCLE;
double distance(Shape& otherShape) override;
;
double circleCircleDistance(Circle& circle1, Circle& cirlce2)
return 0; //pretend this does the calculation
;
double Circle::distance(Shape &otherShape)
switch (otherShape.type)
case CIRCLE:
//Here I get the error
//cannot bind base class object of type Shape to derived class reference Circle& for 2nd argument
return circleCircleDistance(*this, otherShape);
【问题讨论】:
【参考方案1】:您必须将 Shape&
转换为 Circle&
return circleCircleDistance(*this, static_cast<Circle&>(otherShape));
顺便说一句,我会以不同的方式处理您的类型
class Shape
public:
virtual ShapeType get_type() const = 0; // derived classes must override this
virtual double distance(Shape& otherShape) = 0;
;
class Circle : public Shape
public:
ShapeType get_type() const override return CIRCLE; // here's your override
double distance(Shape& otherShape) override;
;
...
switch (otherShape.get_type())
否则,您将遇到type
从派生类/基类中隐藏的情况,具体取决于您访问它的方式。
【讨论】:
哦,当然!谢谢,我试过这个,但要投到 Circle 而不是 Circle&!也感谢您提供有关类型的提示!【参考方案2】:C++ 本身不支持多分派。 多亏了虚拟方法,我们只有一次调度。
因此您可以为您的案例实施double dispatch。
一个(C++17)“替代”选项是使用std::variant
,它具有实现多个调度的std::visit
:
您可以保留或删除它。
struct Circle
Point center;
float radius;
;
struct Rectangle
Point topLeft;
Point bottomRight
;
using Shape = std::variant<Square, Rectangle>;
double distance(const Square&, const Square&);
double distance(const Square&, const Rectangle&);
double distance(const Rectangle&, const Square&);
double distance(const Rectangle&, const Rectangle&);
double distance(const Shape& shape1, const Shape& shape2)
return std::visit([](const auto& shape1, const auto& shape2)
return distance(shape1, shape2);
,
shape1,
shape2);
【讨论】:
好的,谢谢,这似乎是一个有趣的想法,我会研究一下。我看到的一个问题是必须定义 A-B 和 B-A,但我想一旦你有了一个,另一个很容易只需调用交换参数的函数。 在您的试探中,您也必须处理 A-B 和 B-A。因为它确实是对称的,所以一个可以调用另一个,但是这个问题无论如何与多次调度无关。 是的,我想是的,我只需要例如一个 circleSquareDistance 函数,但需要以正确的顺序处理 Circle 和 Square 类中的情况。【参考方案3】:在 c++20 中,您可以使用带有概念的模板专业化来解决此类问题
【讨论】:
以上是关于将基类的对象传递给派生类的引用函数的主要内容,如果未能解决你的问题,请参考以下文章