STL List - 作为指针对象的数据类型
我在使用继承和 STL 列表库时遇到问题...
比如说,我有一个带有两个派生类的抽象基类(其中定义了所有比较运算符)。该列表是在
list<StoreItem*> items;
我插入一个名为 Food 或 Clothing 的派生类(抽象基类 StoreItem)时声明的。我创建了一个即将插入的新 StoreItem 指针:
StoreItem* item = new Food(arguments here);
现在,我想将这个新项目(按顺序)插入到列表中,我的尝试是这样的:
list<StoreItem*>::iterator iter;
for (iter = inventory.begin(); iter != inventory.end(); iter++)
{
if (*item < **iter)
break; // break out to insert
}
inventory.insert(iter, item);
我做错了什么吗?另外,我如何从库存中提取信息? (例如:使用复制构造函数的 Food tempFruit(**iter))。
先感谢您!祝你有美好的一天。
I'm having a problem using inheritance and the STL list library...
Say, I have an abstract base class with two derived classes (where all comparison operators are defined). The list is declared as
list<StoreItem*> items;
I'm inserting a derived class (of the abstract base class, StoreItem) called either Food or Clothing. I make a new StoreItem pointer that's about to be inserted:
StoreItem* item = new Food(arguments here);
Now, I'm wanting to insert this new item (in order) to the list, and my attempt is this:
list<StoreItem*>::iterator iter;
for (iter = inventory.begin(); iter != inventory.end(); iter++)
{
if (*item < **iter)
break; // break out to insert
}
inventory.insert(iter, item);
Is there anything I'm doing wrong? Also, how would I pull the information from the inventory? (ex: Food tempFruit(**iter) using the copy constructor).
Thank you in advance! Have a good day.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您假设从列表中提取的项目是一个 Food 实例;然而,编译器不知道这一点。当您从列表中的项目(表观类型为
StoreItem
的项目)构造Food
的新实例时,您正在尝试调用Food::Food( const StoreItem)
或兼容的东西。为什么?因为迭代器指向StoreItem*
,它可能是StoreItem
对象的实例,或者是从派生的任何类的实例StoreItem
,例如Food
。正如其他发帖者所评论的那样,多态性是成功的关键。您真的需要知道该物品是
食物
吗?如果没有,则访问所有商店商品共享的界面(例如价格、序列号等)。如果您需要了解该项目的具体信息,那么您可以尝试推断其类型:You are assuming that the item you are pulling from the list is a
Food
instance; however, the compiler doesn't know that. When you construct a new instance ofFood
from an item in the list (an item with apparent typeStoreItem
), you are trying to callFood::Food(const StoreItem)
or something compatible. Why? Because the iterator points to aStoreItem*
that could be an instance of aStoreItem
object, or an instance of any class derived fromStoreItem
, such asFood
.As other posters have commented, polymorphism is a key to success. Do you really need to know that the item is a
Food
? If not, then access the interface shared by all store items (like price, serial-number, etc.). If you need to know something specific about the item, then you can try to infer its type:如果您已经定义了
StoreItem::operator<
,这将会起作用,但还有另一种方法可能会更好一些。 STL 已经冷排序了。您可以为StoreItem*
定义<
,然后使用list<...>::sort()
。(您可能已经考虑过定义自己的
SortedItemList
类来处理内部排序。)是的,
tempMovie(**iter)
可以工作,除其他方式外。编辑:
我认为我谈论从库存中取出一些东西为时过早。这是有效的:
请注意,您必须知道此
StoreItem*
实际上指向Food
- 如果它指向Clothing
,您将出现分段错误或更糟的情况。要找到答案,您可以实现自己的StoreItem::whatTypeAmI()
,或者使用 C++ 的运行时类型识别:(请注意,您可以使用
StoreItem*
做很多事情code> 或StoreItem&
而不知道它的类型——多态性是你的朋友。)This will work, provided you've defined
StoreItem::operator<
, but there's another way that might be a little better. The STL has sorting down cold. You could define<
forStoreItem*
, then uselist<...>::sort()
.(And you've probably already thought of defining your own
SortedItemList
class that handles the sorting internally.)And yes,
tempMovie(**iter)
would work, among other ways.EDIT:
I think I spoke too soon about pulling something out of the inventory. This works:
Note that you have to know that this
StoreItem*
actually points to aFood
-- if it points to aClothing
you'll get a segmentation fault or worse. To find out, you could implement your ownStoreItem::whatTypeAmI()
, or use C++'s run-time type identification:(Be aware that you can do a lot with a
StoreItem*
orStoreItem&
without knowing it's type-- polymorphism is your friend.)如果您可以在指向基类的两个指针之间定义比较运算符,则无需编写任何其他代码即可获得有序集合。根据您的应用程序,您可能需要一个集合或堆,甚至可能是一个映射。这是执行此操作的习惯用法...(基数是从字符串公开派生的)。
输出:
能够
面包师
charlie
在发现这个习语之前,你可能会闲逛一段时间。发生的事情是您正在专门使用库模板 std::less for T=base*;然后,它就像魔法一样插入到 std::set (或其他有序容器)的默认比较器参数中。
If you can define a comparison operator between two pointers to your base class, you can get an ordered collection without writing any other code. Depending on your application you might want a set or a heap, maybe even a map. Here's the idiom to do it... (base is publicly derived from string).
output:
able
baker
charlie
It's possible to mill around for a while before discovering this idiom. What's going on is that you're specializing the library template std::less for T=base*; this then slots as if by magic into the default comparator argument for std::set (or other ordered containers).
您可以使用
boost 来代替自制任何解决方案::ptr_list
。如果您打算将指针存储在像容器这样的 STL 中,那么事情会变得容易得多。然后您所需要做的就是为您尝试插入的任何项目定义operator<
。请记住,ptr_list
不适合与共享所有权一起使用。要实现此目的,请在std::list
中使用std::shared_ptrS
并为您的shared_ptr
专门化std::less
> 类型。Instead of homebrewing any solution you could resort to
boost::ptr_list
. It makes life a lot easier if you intend to store pointers in STL like containers. Then all you need is to defineoperator<
for whatever item you are trying to insert. Remember thatptr_list
is not intended to be used with shared ownership. To achieve this usestd::shared_ptrS
in astd::list
and specializestd::less
for yourshared_ptr
type.通过为
StoreItem
指针定义的比较函数,您可以缩短插入代码,如下所示:Insertion:
std::upper_bound
(#include) 假设您的列表已排序,因此如果您始终保持列表排序,则这适用。
至于将数据拉出来,需要考虑两件事:
您可以这样做:
With a comparison function defined for pointers to
StoreItem
you can shorten your insertion code like so:Insertion:
std::upper_bound
(#include <algorithm>
) assumes your list is sorted, so this applies if you keep your list sorted at all times.As to pulling the data back out, there are two things to consider:
You can do this: