stl标准容器的继承问题

sharkoasis 2006-12-01 03:09:03
这两天想到一个问题!不知道stl中容器能否继承,并修改一些默认的函数和操作!
继承是可以的,比如list类!
template <class T>
class My_list :public list<T>
{
public:
void my_fun(){}
}
可以添加一些方法。

现在我想将list变成一个循环链表类,我想修改它的++操作符,看了list的源码,知道++是由_list_iterator类定义的!
不知道怎么做!谁能给个正确的方法?
如果我自己写iterator类,怎么写,怎么和list相连?
...全文
550 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
taodm 2006-12-05
  • 打赏
  • 举报
回复
你的pos可是类成员呀!
sharkoasis 2006-12-05
  • 打赏
  • 举报
回复
这个不是返回值吗?赋不赋给pos应该一样吧!我觉得!
短歌如风 2006-12-05
  • 打赏
  • 举报
回复
return (pos == _list.end()) ? (pos = _list.begin()) : pos;
意思才一样
短歌如风 2006-12-04
  • 打赏
  • 举报
回复
STL中的容器类是可以继承的,但由于STL中的容器类都是没有virtual析构的,所以其衍生类与基类并不符合IS-A关系,这种继承其实是为了重用代码,而从重用代码的角度来看,公有继承不如私有继承,继承不如组合。

如果用公有继承的方式,虽然一开始看上去很方便,所有基类接口都可以继续使用,但如果你需要修改某一方法的规则时就很麻烦了。

>不知道stl中容器能否继承,并修改一些默认的函数和操作!

在公有继承的情况下,所有非多态成员函数都是无法修改其实现的,只能通过重名的方法来“隐藏”,但当把衍生类指针向上映射为基类指针访问时,所有被隐藏的方法又将暴露出来。前面所说的“多态方法”包括虚成员函数以及template-method模式等包含对虚成员函数的调用的成员函数,它们可以在衍生类中进行override。

总而言之,STL中的容器类可以通过“继承”的方法重用其实现,但不推荐从STL类公有继承。最好使用组合的方式重用,也可以考虑使用私有继承。
OOPhaisky 2006-12-04
  • 打赏
  • 举报
回复
但是,很少看到有继承STL类的情况。。。
OOPhaisky 2006-12-04
  • 打赏
  • 举报
回复
这两天想到一个问题!不知道stl中容器能否继承,并修改一些默认的函数和操作!
继承是可以的,比如list类!
template <class T>
class My_list :public list<T>
{
public:
void my_fun(){}
}
可以添加一些方法。
-------------------------------------------------------------------------------------
当然可以继承,STL中的类也是类,所以没问题。C++不像java/c#之类的语言,有final/sealed之类的关键字来使类不能被继承,所以C++中的类都可以继承(当然了,一些手法可以让继承无法通过编译,比如private constructor && virtual inheritance,但是STL中的类没有这些限制)。
0黄瓜0 2006-12-04
  • 打赏
  • 举报
回复
template <class T>
class List
{
private:
list<T> _list;
typedef typename list<T>::iterator iter;
iter pos;

public:
List(){pos=_list.end();}//一个空list和一个有元素的list,end()迭代器应该是一样的
void push(T& i){_list.push_back(i);}
//T pop(){ _list.pop_back();}//将删除最后一个元素和返回最后一个元素分开
void pop()
{
pos=_list.end();//删除元素可能会使先前的迭代器失效,所以要重置pos
_list.pop_back();
}
T top()
{
return _list.top();
}
iter next()
{
if(_list.begin()==_list.end())
throw"没有数据";
if(pos==_list.end())
{
--pos;
return pos;
}
++pos;
if(pos == _list.end())
{
pos=_list.begin();
}
return pos;
//return (pos == _list.end()) ? _list.begin() : pos;
}

iter getpos()
{
if(_list.begin()==_list.end())
throw"没有数据";
return (pos == _list.end()) ? --pos: pos;
}

void print()
{
for(iter p=_list.begin();p!=_list.end();++p)
cout<<*p<<" ";
cout<<endl;
}
};
int main()
{
List<int> iList;

for(int i=1;i<=10;++i)
iList.push(i);

iList.print();

cout<<*(iList.getpos())<<endl;
iList.next();
cout<<*(iList.getpos())<<endl;
iList.next();
cout<<*(iList.getpos())<<endl;
for( i=1;i<=5;++i)
iList.next();
cout<<*(iList.getpos())<<endl;

iList.pop();
iList.print();

return 0;
}
短歌如风 2006-12-04
  • 打赏
  • 举报
回复
如果你用组合实现的话,你就可以让它返回自己定义的迭代子,从而让你的迭代子也符合“循环”的逻辑。

同时,迭代子也应该是通过对list::iterator的组合来实现的。

如果你要保留容器的“begin/end”的概念,则必须在循环链中插入一个无意义的“结束”点。或者实现严格的“循环表”的概念,不再保留“begin/end”的概念。注意end的定义是“最后一个节点之后的位置”,在循环表中,这个位置与“begin”重合了。
pottichu 2006-12-04
  • 打赏
  • 举报
回复
还是使用组合的好.
继承得不偿失.
taodm 2006-12-04
  • 打赏
  • 举报
回复
什么叫“end()占了一位”?
sharkoasis 2006-12-04
  • 打赏
  • 举报
回复
终于找到根源了!
在next函数中,最后使用
return (pos == _list.end()) ? _list.begin() : pos;
这句就会导致循环多走了一位,也就是我说的end占了一位。
而使用
if(pos==_list.end())
pos=_list.begin();

return pos;
就没有此问题!两种写法意思应该一样啊!
谁能解释一下为什么?
sharkoasis 2006-12-01
  • 打赏
  • 举报
回复
顶一下先!
上面的有些问题!不应在构造函数里给pos赋值,因为_list还没初始化!但是end()占一个位置的问题还是没想好怎么解决,高手帮帮忙吧?
sharkoasis 2006-12-01
  • 打赏
  • 举报
回复
template <class T>
class List
{
private:
list<T> _list;
typedef typename list<T>::iterator iter;
iter pos;

public:
List(){pos=_list.begin();}
void push(T& i){_list.push_back(i);}
T pop(){_list.pop_back();}
iter next()
{
++pos;
return (pos == _list.end()) ? _list.begin() : pos;
}

iter getpos()
{
return pos;
}

void print()
{
for(pos=_list.begin();pos!=_list.end();++pos)
cout<<*pos<<" ";
cout<<endl;
}
};
int main()
{
List<int> iList;

for(int i=1;i<=10;++i)
iList.push(i);

iList.print();

cout<<*(iList.getpos())<<endl;
iList.next();
cout<<*(iList.getpos())<<endl;
iList.next();
cout<<*(iList.getpos())<<endl;
for(int i=1;i<=10;++i)
iList.next();

cout<<*(iList.getpos())<<endl;

return 0;
}
应该是这样吧,但是还有一个问题,每次循环end()占了一位!这个有什么好办法解决呢!我觉得这种方法不太好,有没有更好的方法呢?
0黄瓜0 2006-12-01
  • 打赏
  • 举报
回复
mark
短歌如风 2006-12-01
  • 打赏
  • 举报
回复
可以继承,但是不好
要重用STL容器类,最好用组合
taodm 2006-12-01
  • 打赏
  • 举报
回复
可以继承。不过,对你这个问题,不实用,要写的代码太多。
你只要不对iter用++/--,用自己写的next/prev函数即可。
next(list<T>& l, list<T>::iterator iter)
{
++iter;
return (iter == l.end()) ? l.begin() : iter;
}

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧