std::vector无sort成员编译错误及Shape类排序实现求助
Hey there! Let's break down the issues in your code and fix them step by step.
1. The immediate compile error: vector has no sort member function
First off, that error happens because std::vector doesn’t have a built-in sort() method. Sorting standard containers like vector uses the standalone std::sort algorithm from the <algorithm> header. To fix this:
- Add
#include <algorithm>to your top-level includes. - Replace the line
orderedList.sort();with a call tostd::sort, paired with a comparator that knows how to compare yourShape*pointers.
2. Fix operator< const correctness
Your current operator< isn’t marked const, which means it can’t be called on const Shape objects. Since we’ll be dereferencing const Shape* pointers in our comparator, this would cause another compile error. Update the method to:
bool operator<(const Shape& s) const { return Precedes(s); }
3. Fix the typeid portability issue (your ordering won’t work as-is)
typeid(*this).name() returns a compiler-specific string. For example, in GCC, Triangle will show up as 7Triangle (the number is the length of the class name), so your strcmp checks against typeOrderTable will never match.
A reliable, portable fix is to add a virtual method to return the type name explicitly. Modify the Shape class:
class Shape { public: virtual void Draw() const = 0; virtual bool Precedes(const Shape&) const; bool operator<(const Shape& s) const { return Precedes(s); } // Add this virtual method to return a human-readable type name virtual const char* GetTypeName() const = 0; private: // Make this const char* to match string literals static const char* typeOrderTable[]; }; // Update the table to use const char* and nullptr instead of 0 const char* Shape::typeOrderTable[] = {"Rectangle","Square","Triangle", nullptr }; // Rewrite Precedes to use GetTypeName instead of typeid bool Shape::Precedes(const Shape& s) const { const char* thisType = GetTypeName(); const char* argType = s.GetTypeName(); bool done = false; int thisOrd = -1; int argOrd = -1; for (int i=0; !done; i++) { const char* tableEntry = typeOrderTable[i]; if (tableEntry != nullptr) { if (strcmp(tableEntry, thisType) == 0) thisOrd = i; if (strcmp(tableEntry, argType) == 0) argOrd = i; // Check if both types are found (use >=0 since indices start at 0) if ((argOrd >= 0) && (thisOrd >= 0)) done = true; } else done = true; } // Handle cases where a type isn't in the table (put unknown types last) if (thisOrd == -1) return false; if (argOrd == -1) return true; return thisOrd < argOrd; }
Then override GetTypeName in each subclass:
class Square : public Shape { public: virtual void Draw() const { std::cout << "Inside Draw of Square \n" ; } const char* GetTypeName() const override { return "Square"; } }; class Rectangle : public Shape { public: virtual void Draw() const { std::cout << "Inside Draw of Rectangle \n" ; } const char* GetTypeName() const override { return "Rectangle"; } }; class Triangle : public Shape { public: virtual void Draw() const { std::cout << "Inside Draw of Triangle \n" ; } const char* GetTypeName() const override { return "Triangle"; } };
4. Update the DrawAllShapes function
With the fixes above, update your sorting logic to use std::sort and a lambda comparator that dereferences the pointers to use your operator<:
void DrawAllShapes(std::vector<Shape*>& list) { std::vector<Shape*> orderedList = list; // Sort using our custom comparison logic std::sort(orderedList.begin(), orderedList.end(), [](const Shape* a, const Shape* b) { return *a < *b; }); std::vector<Shape*>::iterator it = orderedList.begin(); for (;it!=orderedList.end(); ++it) (*it)->Draw(); }
5. Bonus: Fix memory leaks
You’re allocating shapes with new but never deleting them, which causes memory leaks. Add cleanup in main():
int main() { std::vector<Shape*> vec; vec.push_back(new Triangle); vec.push_back(new Square); vec.push_back(new Rectangle); vec.push_back(new Square); DrawAllShapes(vec); // Clean up allocated memory for (Shape* s : vec) { delete s; } vec.clear(); return 0; }
Now your code will compile, sort shapes according to your typeOrderTable (Rectangle → Square → Triangle), draw them in that order, and clean up memory properly.
内容的提问来源于stack exchange,提问作者Invictus

