【发布时间】:2018-02-10 09:53:31
【问题描述】:
我正在尝试模仿 C++ 中通用列表的 .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> 抽象类,则不会产生错误。
我猜我使用模板化基类的方式在这种情况下是不正确的。
【问题讨论】:
-
您有多个问题:1) C++ 中的对象不像 .NET 或 Java 对象那样工作,它们根本不同 2) 多重继承。有关更多信息,请获取一本好的 C++ 书籍。这些是无法在简短的 stackoverflow.com 答案中完全解释的基本概念。试图依靠您对 .NET 的了解来学习 C++ 会导致无穷无尽的失败和困惑,因为正如我所说,C++ 对象的工作方式完全不同。例如,您是否知道所有方法都必须将
const引用作为参数,而不是值?原因请参阅您的 C++ 书籍。 -
感谢您的 cmets。 1)我完全理解这一点。 2)我不需要一本好书,也不是试图“学习 C++”,但我试图理解为什么模板系统或我的实现,在这种情况下,由于多重继承而产生错误。不依赖 .Net 的任何知识 - 事实上,我已经有一段时间没有接触过它了。
-
对于初学者来说,这与模板无关。相同的编译错误将发生在相同的类结构和图片中任何地方没有模板的情况下。如果你“试图理解”一些关于 C++ 的东西,无论是模板还是其他任何东西,一本好的 C++ 书都是必需的。 C++ 模板不是类,类也不是模板(与 .NET 或 Java 不同,它们完全不像 C++ 模板,即使它们看起来非常相似),错误是由于类继承,而不是与模板相关的任何内容。
-
[OT] 您可以通过直接使用
vector而不是vector上的指针来避免问题(0/3/5 规则)。
标签: c++ templates inheritance abstract-class