std::sort 的多态类型未按预期排序

std::sort of polymorphic types not sorting as expected

我从敏捷软件开发中的 ch9 Open Closed Principle 中获取了示例代码,如下所示,它应该按照下面代码中 table typeOrderTable 给出的顺序按优先级对形状进行排序。好吧,我确实必须添加一个主要代码和测试代码,但几乎复制了书中的代码。但是输出显示它没有按照 table 排序。而且如果我尝试调试代码,代码路径不会进入Shape::Precedes函数。

我该如何解决这个问题?

代码:

#include <typeinfo>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Shape {
public:
    virtual void Draw() const = 0;
    bool Precedes(const Shape& s) const;
    bool operator<(const Shape& s) const {
        return Precedes(s);
    }

private:
    static const char* typeOrderTable[];
};

bool Shape::Precedes(const Shape& s) const {
    const char* thisType = typeid(*this).name();
    const char* argType = typeid(s).name();

    bool done{ false };
    int thisOrd{ -1 };
    int argOrd{ -1 };
    for (int i = 0; !done; ++i) {
        const char* tableEntry = typeOrderTable[i];
        if (tableEntry != 0) {
            if (strcmp(tableEntry, thisType) == 0)
                thisOrd = i;
            if (strcmp(tableEntry, argType) == 0)
                argOrd = i;
            if (argOrd >= 0 && thisOrd >= 0)
                done = true;
        }
        else done = true;
    }
    return thisOrd < argOrd;
}


class Square : public Shape {
public:
    virtual void Draw() const {
        cout << "square\n";
    }
};

class Circle : public Shape {
public:
    virtual void Draw() const {
        cout << "circle\n";
    }
};

class Rectangle : public Shape {
public:
    virtual void Draw() const {
        std::cout << "rectangle\n";
    }
};

const char* Shape::typeOrderTable[] = {
    typeid(Circle).name(),
    typeid(Rectangle).name(),
    typeid(Square).name(),
    0
};

void DrawAllShapes(vector<Shape*> shapes) {
    vector<Shape*> orderedList = shapes;
    sort(orderedList.begin(), orderedList.end());

    for (auto shape : orderedList) {
        shape->Draw();
    }
}

int main() {
    Shape* circle = new Circle();
    Shape* square = new Square();
    Shape* rectangle = new Rectangle();
    Shape* rectangle2 = new Rectangle();

    vector<Shape*> shapes{ rectangle, square, circle, rectangle2 };
    DrawAllShapes(shapes);
    /* should print:
    circle
    rectangle
    rectangle
    square

    but instead prints:
    rectangle
    square
    rectangle
    circle

    ie unsorted - actually it is random in the output
    */
}

您需要更改对 std::sort(...) 的调用以使用比较器。按照您的方式,它是指向正在排序的形状的指针而不是形状,因此不会调用为形状定义的 operator<,而是比较指针的数值。

解决这个问题的一种方法是像这样排序

sort(orderedList.begin(), orderedList.end(),
    [](Shape* s1, Shape* s2) { return s1->Precedes(*s2); }
);

提供一个采用 Shape* 的 lambda 来进行实际比较。