【问题标题】:Covariant Return Type and Object Oriented Programming协变返回类型和面向对象编程
【发布时间】:2020-03-02 08:13:51
【问题描述】:

我定义了一个超类。

class Region
{
public:
    virtual Region translate(int x,int y);
    virtual bool contains(struct point p);
};

现在我有一个定义为 Union 的子类,它基本上采用两个区域的联合。


class Union : public Region
{
    Region r1,r2;

    Union translate(int x,int y) {
        Union translated;
        translated.r1 = r1.translate(x,y);
        translated.r2 = r2.translate(x,y);
        translated.rotateangle=rotateangle;
        return translated;
    }
};

现在我有专门定义为区域子类的区域,即 Rectangle、Triangle 和 Circle,它们有自己的 translate 函数和相同的返回类型。 (即三角形翻译的返回类型为三角形。)

示例代码:

class Triangle : public Region
{
private:

    struct point A,B,C;

public:

    Triangle translate(int x,int y)
    {
        Triangle translated;

        translated.A.x+=x;
        translated.B.x+=x;
        translated.C.x+=x;

        translated.A.y+=y;
        translated.B.y+=y;
        translated.C.y+=y;

        return translated;
    }
};

正如我们所见,在 Union 类中,我们将两个区域合并在一起,我们不知道它们属于哪个子类(即它们是三角形、圆形还是矩形),但我们仍然想翻译区域 r1 和 r2 在每个区域上调用 translate 函数。

既然我们不能在不知道它们的类型的情况下对 r1 和 r2 调用 translate,我们如何实现这个功能来实现这个层次结构?

【问题讨论】:

  • 这是一个闪烁的红旗:class Union : public Region { Region r1,r2; ... 我读为 Union 是一个包含两个 Regions 的 Region
  • 请注意,协变(和逆变)仅适用于 C++ 中的指针和引用。
  • translated.rotateangle 这是什么意思?没有名为rotateangle的成员
  • 为什么你认为你不能在r1r2 上调用translate?这正是接口(也称为纯虚拟类)的用途。
  • 请检查您的示例代码,某些事情是可疑的,细节很重要。首先是已经提到的组合和继承的混合然后Region::translate返回一个指针,但Triangle::translate返回一个Triangle

标签: c++ function class oop object


【解决方案1】:

您需要通过引用或指针将Regions 存储在Union 中。就目前而言,您不能Union 中存储Triangles、Rectangles 等,您将复制(空?)Region 基本子对象。

类似

#include <memory>

struct Point
{
    int x = 0, y = 0;
};

class Region
{
public:
    virtual std::unique_ptr<Region> translate(int x,int y) = 0;
    virtual bool contains(Point p) = 0;
};

class Union : public Region
{
    std::unique_ptr<Region> r1, r2;
    int rotateangle;
public:
    std::unique_ptr<Region> translate(int x,int y) override {
        auto translated = new Union;

        translated->r1 = r1->translate(x,y);
        translated->r2 = r2->translate(x,y);
        translated->rotateangle = rotateangle;

        return std::unique_ptr<Region>(translated);
    }

    bool contains(Point p) override {
        return r1->contains(p) || r2->contains(p);
    }
};

class Triangle : public Region
{
    Point A,B,C;
public:
    std::unique_ptr<Region> translate(int x,int y) override {
        auto translated = new Triangle;

        translated->A.x = A.x + x;
        translated->B.x = B.x + x;
        translated->C.x = C.x + x;

        translated->A.y = A.y + y;
        translated->B.y = B.y + y;
        translated->C.y = C.y + y;

        return std::unique_ptr<Region>(translated);
    }

    bool contains(Point p) override {
        return false; // TODO
    }
};

请注意,您不必知道Union::translate 已返回一个(指向)Union 的(指针)。

【讨论】:

  • 在班级联盟。 r1 和 r2 是类区域的指针。现在当我们在做r1-&gt;translate(x,y) 时,我们正在向下转换指针类型(因为在一个区域中可以是三角形、矩形或圆形。)所以我们不需要显式地进行类型转换吗? As from this question for reference
  • 虚函数的要点是你调用了最衍生的版本。请注意,Region::translate缺少定义。
  • 所以基本上我的理解是,在三角形类的翻译函数中,我们返回的是区域指针而不是三角形指针。 return std::unique_ptr&lt;Region&gt;(translated);这行代码就是这个意思吧?
  • @KudoShinichi 是的,您正在返回一个指向区域的指针,它指向一个 Triangle
猜你喜欢
  • 2020-06-14
  • 2017-02-28
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
相关资源
最近更新 更多