社区
C语言
帖子详情
STL容器能否包含多态类型,如果可以的话,怎样才能做到安全有效?
anrxhzh
2002-04-12 02:45:04
希望定义一个容器能够包含整个类层次中的所有非抽象类的对象。
...全文
177
21
打赏
收藏
STL容器能否包含多态类型,如果可以的话,怎样才能做到安全有效?
希望定义一个容器能够包含整个类层次中的所有非抽象类的对象。
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
21 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
anrxhzh
2002-04-12
打赏
举报
回复
我又搞错了,shared_ptr<T>中的T可以为抽象基类,它只是要求T的析构函数必须为public。
在类工厂模式下析构函数为protected或者private是很常见的,在那种情况下就需要其他方法了,我想那时使用http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html#pointer_deriv 上的方法就显得很自然了,类工厂和容器的例子在More Effective C++ Item 25上也有论述。
好了,终于可以告一段落了,谢谢大家的帮忙。
anrxhzh
2002-04-12
打赏
举报
回复
to babysloth(小懒虫虫) :
非常感谢你的解答,我想你是对的。看来我把这个问题理解错了,这不是一个多态的问题,而是一个管理指针的问题。其实就算什么都不想,直接把指针放到容器里,也不会在多态上造成问题,因为所有跟多态有关的实现细节都已经被编译器藏到了指针里,我真是杞人忧天。
真正的问题出现如何对容器中的指针进行管理上,假如直接把指针放到容器里,然后在进行删除元素操作和容器的析构器中释放元素指向的内存,听起来似乎井井有条,但是如果一个容器中有多个元素指向同一个对象或者多个指向同一个对象的元素被包含到多个容器中,就会带来一片混乱。
那么用标准库中的auto_ptr来管理指针又会如何呢?情况可能会更糟,不但老问题不能解决,还带来了新问题,auto_ptr只是简单的将指针的管理权在对象之间转移,假如在对容器进行操作的算法中将元素的管理权交给了临时对象,那么当算法完成后临时对象将自动地释放该元素指向的内存,结果将不堪设想。
终于轮到shared_ptr登场了,这个比auto_ptr复杂得多的东东管理的是对象的引用计数,当计数为0时自动释放内存,呵呵,真是个好管家。
上面啰嗦了这么多,主要是给自己看,不把它写出来我始终觉得脑子很乱。
言归正传,shared_ptr<T>要求T不能为抽象基类并且能够访问T的析构函数,这就造成了绝大多数基类不能被使用。
革命尚未成功,同志还须努力。
挺拔的劲松
2002-04-12
打赏
举报
回复
应该保存指针才行吧!
babysloth
2002-04-12
打赏
举报
回复
问题复杂的原因是被我们搞复杂了。
问题本身是简单的。
stl容器的设计者还没笨到连这个问题都没考虑。
对于我上面那段代码
for(list_type::iterator i = ll.begin(); i != ll.end(); ++i)
i->InterfaceOfBase();
也是多态调用。
shared_ptr是对指针的包装!
babysloth
2002-04-12
打赏
举报
回复
2 anrxhzh
您恐怕还没明白我写的那段代码
那里面储存的是指针,何来类型丢失???
anrxhzh
2002-04-12
打赏
举报
回复
我估计是要使用Abstract Factory之类的重型武器了。
anrxhzh
2002-04-12
打赏
举报
回复
babysloth(小懒虫虫) 的方法是有问题的,原因在于容器认为其包含所有对象都是基类对象,这样肯定会造成类型丢失,这就是Scott Meyers所讲的Never treat arrays polymorphically 。
我把问题详细地描述一下:
存在一个单根的类层次,基类为抽象类Base。
要求实现容器类Container,满足一下要求:
1.可以包含所有非抽象的子类对象。
2.Container不必知道类层次的具体结构,也不必知道Base的接口。
3.对容器对象进行操作不能造成类型丢失。
客户可以编写这样的代码:
void Test(Container& c)
{
for(Container::iterator i(c.begin());i<c.end();++i)
(*i).InterfaceOfBase();
}
全部的奥妙在于对InterfaceOfBase的调用是多态的。
babysloth
2002-04-12
打赏
举报
回复
这段代码在gcc、vc、bcc里都没有问题。
2 prototype
好象不是限制模板参数的问题吧^_^
babysloth
2002-04-12
打赏
举报
回复
列代码出来吧,呵呵,看看是不是这个意思
#include <list>
#include <boost/shared_ptr.hpp>
class A{};
class C: public A{};
int main()
{
typedef boost::shared_ptr<A> element_type;
typedef std::list<element_type> list_type;
list_type ll;
ll.push_back(element_type(new C));
}
prototype
2002-04-12
打赏
举报
回复
to anrxhzh(百宝箱):
i read the other posts and realized my understanding of your problem might be different than the others's.
here is my understanding:
you have:
class A;
class B : public A;
class C : public B;
template <typename T>
class container;
you want that 'T' should only be allowed to be 'A', 'B', 'C', not any other types.
if this is your problem ...
babysloth
2002-04-12
打赏
举报
回复
呵呵,抱歉,没看清楚。
shared_ptr不只是解决共享的问题,事实上,这里也没有这个问题。
我的意思是,把基类的指针放进shared_ptr,再把shared_ptr作为容器放进容器就可以了。
anrxhzh
2002-04-12
打赏
举报
回复
希望大家看看已有的解决方案,应该有启发意义。
http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html#pointer_deriv
neccui
2002-04-12
打赏
举报
回复
你没理解我的意思。
我的意思是, 一个给定参数的容器里面的对象大小是固定的。
anrxhzh
2002-04-12
打赏
举报
回复
to babysloth(小懒虫虫):
shared_ptr 解决的是共享对象的问题,而不是多态的问题,这是两个完全不同的问题,仅依靠模板肯定是不能解决多态问题的。
babysloth
2002-04-12
打赏
举报
回复
容器要求大小固定?不是吧?
neccui
2002-04-12
打赏
举报
回复
容器虽然不是数组,但是也是要求大小固定的,这个就没法解决。
babysloth
2002-04-12
打赏
举报
回复
用boost库里的shared_ptr包装好,直接往容器里放就可以了。
这也是boost:shared_ptr设计的初衷之一。
anrxhzh
2002-04-12
打赏
举报
回复
to afsfop:
我明白多态容器将带来很多麻烦,但是有时确实需要它,就像多重继承一样。容器!=数组,所以应该不存在Scott Meyers所讲的限制。我在
http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html#pointer_deriv
上找到了两种实现方法,可惜都需要修改类层次的现有接口,不知道有没有更完美的解决方案。
to prototype:
希望能详细地讲一下,多谢。
boyfling
2002-04-12
打赏
举报
回复
http://www.csdn.net/expert/topic/639/639286.xml?temp=8.961123E-02
prototype
2002-04-12
打赏
举报
回复
one way for takling this problem is to use typelist and static assertion (+ a little bit template meta-programming knowledge).
another is to use typetraits (maybe better?).
加载更多回复(1)
STL
容器
使用总结
第1条:慎重选择
容器
类型
。 标准
STL
序列
容器
:vector、string、deque和list。 标准
STL
关联
容器
:set、multiset、map和multimap。 非标准序列
容器
slist和rope。slist是一个单向链表,rope本质上是一“重型”string。 非标准的关联
容器
hash_set、hase_multiset、hash_map和hash_mult
C++中的
STL
与各种
容器
的底层实现
STL
具体分为哪几个部分? 首先我是基于GNUC2.9的
STL
源码学习的,他和4.9还是有挺多不同的,不过对于帮助我理解标准模板库还是2.9更好。
STL
标准模板库主要分为六个部分:最重要的三个是
容器
、算法、迭代器。另外三个是分配器、仿函数和适配器。 2.9的
STL
主要运用的是泛型编程的思想,它和我们的面向对象还是有些许不同的,面向对象最重要的思想是运行时
多态
,而泛型编程时编译时
多态
,另外面向对象通常会把数据和算法放在一个对象中,而在
STL
中将数据和算法分开,各自实现自己,通过迭代器链接。
容器
:就是
STL
容器
的选择总结
http://blog.sina.com.cn/s/blog_bf5abc9501016406.html 第1条:慎重选择
容器
类型
。 标准
STL
序列
容器
:vector、string、deque和list。 标准
STL
关联
容器
:set、multiset、map和multimap。 非标准序列
容器
slist和rope。slist是一个单向链表,rope本质上是一“重型”st
【新特性】C++
STL
容器
和C++11 新特性介绍(持续更新)
STL
⼀共提供六⼤组件,包括
容器
,算法,迭代器,仿函数,配接器和配置器,彼此可以组合套⽤。
容器
通过配置器取得数据存储空间,算法通过迭代器存取
容器
内容,仿函数可以协助算法完成不同的策略变化,配接器可以应⽤于
容器
、 仿函数和迭代器。
容器
: 各种数据结构,如 vector, list, deque, set, map,⽤来存放数据, 从实现的⻆度来讲是⼀种类模板。算法: 各种常⽤的算法,如 sort(插⼊,快排,堆排序), search(⼆分查找), 从实现的⻆度来讲是⼀种⽅法模板。..............
关于
STL
容器
实现,非侵入式
容器
+Iterator框架和“侵入式”
容器
实现的思考
嗯,看Bjarne的《The C++ Programming Language》的时候记的。刚刚又看到,整理到BLOG上吧。 对于Iterator实现的缺点,即虚函数的调用造成的开销,解决方法只有抹去虚函数,然而这样又如何做到
多态
? 对于“侵入式”
容器
(注:即
容器
内元素需要继承
容器
框架提供的特定接口/超类才能放入
容器
的设计,如Java中只有Object的子类才能进入 Java的
C语言
69,371
社区成员
243,080
社区内容
发帖
与我相关
我的任务
C语言
C语言相关问题讨论
复制链接
扫一扫
分享
社区描述
C语言相关问题讨论
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章