Lyt
posts - 16,comments - 61,trackbacks - 0
最近由于需要频繁使用Dictionary,于是就动手实现了一个,希望和List可以随意地换来换去。
//IList.h
template<typename _Type>
class IIList : public ICollection<_Type>{};

//List.h
template<typename _Type>
class List : public IList<_Type>{};

//IDictionary.h
template<typename TKey, typename TValue>
class IDictionary : public ICollection<Pair<TKey, TValue>>{};
我希望IDictionary.h提供一个ToList() GetKeys() GetValues() 的操作,如果返回IList:

error C2682: cannot use 'dynamic_cast' to convert from 'const Lyt::Collection::List<_Type> *' to 'Lyt::Collection::IList<_Type> *' e:\c++\library\library\library\collection\dictionary.h 171

为啥会有编译错误,至今不明,明明List继承了IList怎么还会转换失败=  =

还有另外一个问题,在实现GetKeys()时,我希望是返回IList而非List,这样如果我以后有其他关于List的实现就不需要修改代码了,考虑到内存泄漏的问题,我只想到两种解决方法,不知道到底怎么折腾才合适,求解答。

//方法一
#include "List.h"
template
<typename TKey, typename TValue>
class Dictionary : public IDictionary<TKey, TValue>
{
protected:
  List
<Pair<TKey, TValue>> Data;
public:
  AutoPtr
<IList<Pair<TKey, TValue>>> GetKeys()const
  {
    AutoPtr
<IList<Pair<TKey, TValue>>> Result=new List<TKey>//用引用计数实现的智能指针
    /**/
  }
};

//方法二
#include "List.h"
template
<typename TKey, typename TValue>
class Dictionary : public IDictionary<TKey, TValue>
{
protected:
  List
<Pair<TKey, TValue>> Data;
  List
<TKey> Keys; //本来我只需要一个List来存放东西就够了,这样我在其他的Add、Remove等操作中都要多折腾一个Keys,是不是没有必要?
public:
  
const IList<TKey>* GetKeys()const
  {
    
return dynamic_cast<IList<TKey>*>(&Keys);
  }
};
posted on 2009-10-15 09:44 Lyt 阅读(1441) 评论(5)  编辑 收藏 引用 所属分类: 数据结构

FeedBack:
# re: Dictionary的囧状
2009-10-15 13:43 | OwnWaterloo
1.
error C2682: cannot use 'dynamic_cast' to convert from 'const Lyt::Collection::List<_Type> *' to 'Lyt::Collection::IList<_Type>
 
明白了吗?
 
2.
IDictionary.h  include  List.h
Dictionary.h include IDictionary.h
相互包含在哪?
 
 
 
C++不是这么用的……  被C#熏昏头的同学……
  回复  更多评论
  
# re: Dictionary的囧状
2009-10-15 15:39 | Lyt
@OwnWaterloo
没有相互包含的状况,抱歉…
已经解决const的问题了,谢。

数据结构的确是模仿.NET的,呃,不太明白为什么你说C++不是这么用的?  回复  更多评论
  
# re: Dictionary的囧状
2009-10-15 22:30 | OwnWaterloo
@Lyt
你也发现问题了不是? 内存不好管理。

如果你用GP的思想去实现Dictionary, GetKeys可以很简单,并且很高效的实现。
用OOP? 就等着承受虚函数开销以及内存管理的困扰吧。。。
然后,你又会为此去写智能指针, 写内存池, 写锁 ……

你可以把这些当作练习…… 但这不是C++的style ……  回复  更多评论
  
# re: Dictionary的囧状
2009-10-15 22:52 | OwnWaterloo
我说具体一点吧……
如果用GP(代码一切从简):
 
template<typename T>
class /*array*/list {
    T *first,*last_;
public:
    typedef T* iterator;
    typedef const T* const_iterator;
 
    iterator begin() { return first_; }
    iterator end() { return last_; }
    const_iterator begin() const { return first_; }
    const_iterator end() const { return last_; } 
    // ...
};
 
要迭代一个容器:
list<int> l;
for ( list<int>::iterator first = l.begin(), last = l.end(), first!=last; ++first)
    visit_element( *first );
 
而你遇到的问题就是:
list<pair<key,value> > d;
如何得到一个迭代器, 仅仅访问key部分, 而不访问value部分。
 
template<class It>
class project_first {
    It it_;
public:
    project_first( It it ) : it_(it) {}
    typename std::iterator_traits<It>::value_type::first_type&
        operator*() const { return it->first; }
    // 再实现 ++, -- +n 等操作...
};
 
for ( project_first first = d.begin(), last = d.end(); first!=last; ++first)
    visit_key( *first );
 
 
如果d是 list<tuple<key,value> > 类型, project_iterator还可以做得更范化一些。
 
没有虚函数调用,没有动态内存分配。
并且,和stl的算法,boost的算法,以及其他C++组件合作良好。
  回复  更多评论
  
# re: Dictionary的囧状
2009-10-15 23:14 | OwnWaterloo
C#的template能做什么我不太清楚。

C++支持编译时的ducking type机制。
抛弃这种强大的抽象机制不用, 转而在C++这种暂不提供GC的语言中使用接口来作为数据结构之间的纽带 ……
所以…… 我说这不是C++的style ……

还有一些小地方。 比如main 的返回类型是int, 而不是C#中的void。
以单下划线接大写字母开头,以及以双下划线开头的标识符在C++中是被保留的。
最好不要将C#中的那些习惯带到C++中来……
用Type, Type_, 别用_Type。

这些被保留的标识符不会被永远保留。 _Bool, _LongLong, _Complex已经出现。



http://www.cppblog.com/Streamlet/
这位同学, 和你在做类似的事情, 也遇到了类似的问题。
你可以参考参考……  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理