いくつかの問題に遭遇しながら、単純なデータ構造ライブラリを作成しています。
3つのファイルを書きました。collections.h はヘッダー ファイル、collections.cpp はヘッダー ファイルで宣言されたメソッドを実装するため、main.cpp はテスト用です。しかし、コンパイルエラーが発生します:
List::GetCount() const への未定義の参照。
List::IsEmpty() const への未定義の参照。
List::Add(int); への未定義の参照;
...// 等々。
以下にコードを提供します。どこに問題がありますか?
コレクション.h:
#ifndef COLLECTIONS_H
#define COLLECTIONS_H
#include <windows.h>
#include <stdexcept>
template<typename T>
class ISequenceList
{
protected:
ISequenceList() { }
public:
virtual int GetCount() const = 0;
virtual bool IsEmpty() const = 0;
virtual void Add(T item) = 0;
virtual void AddRange(const T *items, int length) = 0;
virtual T &ElementAt(int index);
virtual bool InsertAt(T item, int index);
virtual bool Remove(T item) = 0;
virtual bool RemoveAt(int index) = 0;
virtual bool Contains(T item) = 0;
};
template<typename T>
class List : public ISequenceList<T>
{
private:
int _count;
int _capacity;
T *_array;
void ExpandCapacity();
public:
List(int capacity = 100)
{
if (capacity <= 0)
std::__throw_invalid_argument("The capcity can't be 0 or below.");
this->_count = 0;
this->_capacity = capacity;
this->_array = (T*)malloc(_capacity* sizeof(T));
}
List(const List &other)
{
if (this == other)
return;
this->_count = other->_count;
this->_capacity = other->_capacity;
free(_array);
this->_array = other->_array;
}
List &operator=(const List &other)
{
this = other;
}
~List()
{
if (_array)
free(_array);
}
int GetCount() const;
bool IsEmpty() const;
T &ElementAt(int index);
void Add(T item);
void AddRange(const T *items, int length);
bool InsertAt(T item, int index);
bool Remove(T item);
bool RemoveAt(int index);
bool Contains(T item);
};
#endif
コレクション.cpp:
#include "collections.h"
template<typename T>
void List<T>::ExpandCapacity()
{
T *temp = this->_array;
this->_array = (T*)malloc((this->_capacity << 1) * sizeof(T));
memcpy(this->_array, temp, this->_capacity * sizeof(T));
this->_capacity = this->_capacity << 1;
free(temp);
}
template<typename T>
int List<T>::GetCount() const
{
return this->_count;
}
template<typename T>
bool List<T>::IsEmpty() const
{
return this->_count == 0;
}
template<typename T>
void List<T>::Add(T item)
{
this->_array[_count] = item;
_count++;
if (_count == _capacity)
this->ExpandCapacity();
}
template<typename T>
void List<T>::AddRange(const T *items, int length)
{
if (length <= 0)
std::__throw_invalid_argument("The length can't be 0 or below.");
if (!items)
std::__throw_invalid_argument("The items can't be null");
int totalLength = this->_count + length;
if (totalLength >= this->_capacity)
{
T *temp = this->_array;
this->_array = (T*)malloc((totalLength << 1) * sizeof(T));
memcpy(_array, temp, this->_capacity);
free(temp);
}
this->_array += this->_capacity;
memcpy(_array, items, length * sizeof(T));
this->_capacity = totalLength << 1;
this->_count += length;
}
template<typename T>
T &List<T>::ElementAt(int index)
{
if (index < 0 || index >= _count )
std::__throw_invalid_argument("The index is out of bound.");
return _array[index];
}
template<typename T>
bool List<T>::InsertAt(T item, int index)
{
if (index < 0 || index > _count)
return false;
if (index == _count)
{
this->Add(item);
return true;
}
for (int i = _count; i > index; i--)
{
_array[i] = _array[i - 1];
}
_array[index] = item;
_count++;
if (_count == _capacity)
this->ExpandCapacity();
return true;
}
template<typename T>
bool List<T>::Remove(T item)
{
for (int i = 0; i < _count; i++)
{
if (_array[i] == item)
{
for (int j = i; j < _count; j++)
{
_array[j] = _array[j + 1];
}
_count--;
return true;
}
}
return false;
}
template<typename T>
bool List<T>::RemoveAt(int index)
{
if (index < 0 || index >= _count)
return false;
for (int j = index; j < _count; j++)
{
_array[j] = _array[j + 1];
}
_count--;
return true;
}
template<typename T>
bool List<T>::Contains(T item)
{
for (int i = 0; i < _count; i++)
{
if (_array[i] == item)
return true;
}
return false;
}
main.cpp:
#include "collections.h"
#include <iostream>
int main()
{
List<int> *seqList = new List<int>();
seqList->Add(5);
int arr[100] = {0};
seqList->AddRange(arr, 50);
seqList->ElementAt(5) = 111;
seqList->InsertAt(100, 15);
seqList->Remove(50);
seqList->ElementAt(44) = 44;
seqList->RemoveAt(44);
if (seqList->Contains(111))
std::cout << "Yes" << std::endl;
for (int i = 0; i < seqList->GetCount(); i++)
{
std::cout << seqList->ElementAt(i) << "\t";
}
return 0;
}
List ですべてのメソッドを定義しましたが、コンパイラが認識できないのはなぜですか? 問題はどこだ?私を助けてくれてありがとう..
注: 私のアイデアは Code::Blocks です