#c #polymorphism #overloading
Вопрос:
Я взял пример кода из принципа ch9 Open Closed в гибкой разработке программного обеспечения, как показано ниже, который должен сортировать фигуры по приоритету в порядке, указанном таблицей typeOrderTable в приведенном ниже коде. Ну, мне действительно пришлось добавить основной и тестовый код, но я в значительной степени скопировал код книги. Но вывод показывает, что он не сортируется в соответствии с таблицей. И если я попытаюсь отладить код, путь к коду не будет указывать функцию Shape::Предшествует.
Как я могу это исправить?
Код:
#include <typeinfo>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Shape {
public:
virtual void Draw() const = 0;
bool Precedes(const Shapeamp; s) const;
bool operator<(const Shapeamp; s) const {
return Precedes(s);
}
private:
static const char* typeOrderTable[];
};
bool Shape::Precedes(const Shapeamp; 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 amp;amp; thisOrd >= 0)
done = true;
}
else done = true;
}
return thisOrd < argOrd;
}
class Square : public Shape {
public:
virtual void Draw() const {
cout << "squaren";
}
};
class Circle : public Shape {
public:
virtual void Draw() const {
cout << "circlen";
}
};
class Rectangle : public Shape {
public:
virtual void Draw() const {
std::cout << "rectanglen";
}
};
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
*/
}
Комментарии:
1. При сортировке сравниваются значения указателей (т. Е. адреса), а не содержимое, на которое указано. Вам нужно использовать пользовательский компаратор при вызове сортировки.
2.Примечание: начиная с C 11 не рекомендуется использовать необработанные указатели и вручную очищать память. Использовать
std::unique_ptr
godbolt.org/z/Prbhdb
Ответ №1:
Вам нужно изменить вызов на std::sort (…), чтобы использовать компаратор. Как у вас есть, это указатели на сортируемые фигуры, а не фигуры, поэтому operator<
определенные для фигур не будут вызываться, вместо этого будут сравниваться числовые значения указателей.
Один из способов исправить это-отсортировать следующим образом
sort(orderedList.begin(), orderedList.end(),
[](Shape* s1, Shape* s2) { return s1->Precedes(*s2); }
);
предоставление лямбда Shape*
-кода для фактического сравнения.