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 来进行实际比较。
我从敏捷软件开发中的 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 来进行实际比较。