我试图模仿C ++中通用List的.Net实现。
我已经充实了各种interfaces
纯粹的虚拟抽象类,如下所示:
template <typename T>
class ICollection {
public:
virtual void Add(T item) = 0;
virtual void Clear(void) = 0;
virtual bool Contains(T item) = 0;
virtual void Remove(T item) = 0;
virtual int32_t Count(void) const = 0;
};
template <typename T>
class IList : public ICollection<T> {
public:
virtual T Item(int32_t index) = 0;
virtual int32_t IndexOf(T item) = 0;
virtual void Insert(int32_t index, T item) = 0;
virtual void RemoveAt(int32_t index) = 0;
};
现在,当我尝试按如下方式实现我的主List
类时:
template <typename T>
class List : public IList<T>, public ICollection<T> {
public:
List(void);
List(int32_ capacity);
// ICollection<T>
void Add(T item);
// other functions from ICollection
// IList<T>
T Item(int32_t index);
// other functions from IList
void AddRange(IList<T> items);
private:
typedef vector<T> ListType;
ListType *m_pList;
};
template <typename T>
List<T>::List(void) {
m_pList = new ListType();
}
template <typename T>
void List<T>::Insert(uint32_t index, T item) {
// Insert an entry into the list at the specified offset
m_list->insert(index, item);
}
// Implementation of other functions here...
我尝试使用List<T>
类时如下:
List<int32_t> myList;
发出警告说:
In instantiation of 'class List<long int>':
required from here
warning: direct base 'ICollection<long int>' inaccessible in 'List<long int>' due to ambiguity [enabled by default]
class List : public IList<T>, public ICollection<T> {
^
后面跟着以下错误:
In instantiation of 'void List<T>::Insert(uint32_t, T) [with T = long int; uint32_t = long unsigned int]':
required from here
error: no matching function for call to 'std::vector<long int, std::allocator<long int> >::insert(uint32_t&, long int&)'
m_list->insert(index, item);
^
note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::iterator, const value_type&) [with _Tp = long int; _Alloc = std::allocator<long int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<long int*, std::vector<long int, std::allocator<long int> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = long int*; std::vector<_Tp, _Alloc>::value_type = long int]
vector<_Tp, _Alloc>::
^
note: no known conversion for argument 1 from 'uint32_t {aka long unsigned int}' to 'std::vector<long int, std::allocator<long int> >::iterator {aka __gnu_cxx::__normal_iterator<long int*, std::vector<long int, std::allocator<long int> > >}'
如果我修改List<T>
类的声明以删除IList<T>
和ICollection<T>
抽象类,则不会生成错误。
我猜测我在这种情况下使用模板化基类的方式不正确。
答案 0 :(得分:1)
此问题与模板没有直接关系。
class A {
public void f() {}
};
class B : public A {};
class C : public A, public B {};
int main() {
C c;
c.f(); // Error: ambiguous base class!
}
继承类时,派生类包含基类的对象,称为基类子对象。因此,在我的示例中,每个B
都包含A
。每个C
都包含A
和B
。问题是,当我尝试将f
作为C
的成员调用时,编译器需要找到A
子对象来调用它。但是有两种类型的子对象!一个是C
直接继承的,另一个是继承的B
子对象。所以编译器无法弄清楚我的意思。
这种情况下的解决方案是不要继承两次类。在我的示例中,C
不需要直接继承A
,因为继承B
会为其提供间接A
子对象并访问其所有成员。
在您的情况下,List<T>
不需要直接继承ICollection<T>
。只需从IList<T>
派生出来就足够了。
(在其他情况下,使用“虚拟继承”会很有用,它告诉编译器“只为这种类型创建一个基类子对象,即使我在某些派生类中间接地多次继承它”。但是对于你的代码来说可能有点过分了。)