简体   繁体   English

将基类的对象传递给派生类的引用函数

[英]Passing object of base class to function of reference to derived class

I'm trying to write code which can find the distance between lots of different types of shapes.我正在尝试编写可以找到许多不同类型形状之间距离的代码。 I've defined a base class Shape with a virtual distance(Shape& otherShape) function to find the distance to another shape and then want to define that for all my derived classes.我已经定义了一个带有virtual distance(Shape& otherShape)函数的基类Shape来查找到另一个形状的距离,然后想为我的所有派生类定义它。

The problem is that there are lots of possible pairs of shapes, so my solution was to define a set of distance functions outside the classes (circle-circle, circle-square, square-tri etc.) and then call the corresponding one from the distance function.问题是有很多可能的形状对,所以我的解决方案是在类(圆-圆、圆-正方形、正方形-三等)之外定义一组距离函数,然后从距离函数。 I've added a mini example of what I mean below, with just one derived class Circle to demonstrate the problem.我在下面添加了一个小例子来说明我的意思,只有一个派生类Circle来演示这个问题。

When I try and call my specific circleCircleDistance function I get an error because it can't convert the base class into the derived class.当我尝试调用特定的circleCircleDistance函数时,出现错误,因为它无法将基类转换为派生类。 Is there any way I can address this or will my design as it stands just not work?有什么办法可以解决这个问题,或者我的设计就不能正常工作?

enum ShapeType{CIRCLE, 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);
            
    }
}

You would have to cast the Shape& to a Circle&您必须将Shape&转换为Circle&

return circleCircleDistance(*this, static_cast<Circle&>(otherShape));

As an aside, I'd handle your types a bit differently顺便说一句,我会以不同的方式处理您的类型

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()){

Otherwise you're going to get into a situation where type is shadowed from the derived/base classes depending how you access it.否则,您将遇到type从派生类/基类中隐藏的情况,具体取决于您访问它的方式。

Multiple dispatch is not natively supported in C++. C++ 本身不支持多分派。 We only have single dispatch thanks to virtual method.由于虚拟方法,我们只有一个分派。

So you can implement double dispatch for your cases.所以你可以为你的案例实现双重调度

An (C++17) "alternative" option is to use std::variant , which has std::visit which implement multiple dispatch:一个(C++17)“替代”选项是使用std::variant ,它具有实现多重分派的std::visit

You can keep inheritance or drop it.您可以保留继承权或放弃继承权。

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

在 c++20 中,您可以将模板特化与此类问题的概念结合使用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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