[英]C++ Error in creating a linked list of an object that contains a linked list and a string
在下面的程序中,我正在創建一個帶有一個string
和一個linkedlist<int>
。
由於main()
的obj
,我一直遇到未解決的問題。 錯誤提示:
錯誤LNK2019:未解析的外部符號“ public:__thiscall List :: List(class List const&)”(?? 0?$ List @ H @@ QAE @ ABV0 @@ Z)在函數“ public:__thiscall Data :: Data中引用” (類Data const&)”(?? 0Data @@ QAE @ ABV0 @@ Z)
main.cpp
#include "List.h"
#include <string>
#include <iostream>
#include <fstream>
#include <utility>
using namespace std;
template <class Object>
void printList( const List<Object> & theList ) // SIMPLE PRINT FUNCTION
{
if( theList.isEmpty( ) )
cout << "Empty list" << endl;
else
{
ListItr<Object> itr = theList.first( );
for( ; !itr.isPastEnd( ); itr.advance( ) )
cout << itr.retrieve( ) << " ";
}
cout << endl;
}
class Data
{
public:
Data(){
keyword = "";
List<int> pages;
}
void addNewData(string key, int article){
ListItr<int> pageitr = pages.zeroth();
keyword = key;
pages.insert(article, pageitr);
}
void addNewPage(int article){
ListItr<int> pageitr = pages.zeroth();
if(!pages.isExist(article))
pages.insert(article, pageitr);
}
bool operator==( const Data & rhs ){
if( this->keyword == rhs.keyword)
{
return true;
}
return false;
}
bool operator!=( const Data & rhs ){
if( this->keyword != rhs.keyword )
{
return true;
}
return false;
}
private:
string keyword;
List<int> pages;
};
int main( )
{
List<Data> trialdata;
ListItr<Data> dataItr;
ifstream input;
string s,k;
int count = 0;
string filename = "docdb.txt";
input.open(filename.c_str());
if (input.fail() )
{ cout << "could not open file " << filename << endl;
return 0;
}
/*while(input >> s){
input >> k;
addtoList(s, stoi(k), *trialdata);
}*/
return 0;
}
該主程序的相關頭文件稱為List.h
它來自我的課程幻燈片。 我添加了一個功能,並在沒有創建對象的情況下對其進行了測試。 工作正常。 因此,我認為我的對象存在一個問題,即它無法在鏈接列表中創建鏈接列表。
#ifndef LIST_H
#define LIST_H
using namespace std;
#include <iostream>
template <class Object>
class List; // Incomplete declaration.
template <class Object>
class ListItr; // Incomplete declaration.
class BadIterator {
public:
BadIterator() {}
};
template <class Object>
class ListNode
{
ListNode( const Object & theElement = Object( ),
ListNode * n = NULL )
: element( theElement ), next( n ) { }
Object element;
ListNode *next;
friend class List<Object>;
friend class ListItr<Object>;
};
template <class Object>
class ListItr
{
public:
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const
{ return current == NULL; }
void advance( )
{ if( !isPastEnd( ) ) current = current->next; }
const Object & retrieve( ) const
{ if( isPastEnd( ) ) throw BadIterator();
return current->element; }
private:
ListNode<Object> *current; // Current position
ListItr( ListNode<Object> *theNode )
: current( theNode ) { }
friend class List<Object>; // Grant access to constructor
};
template <class Object>
class List
{
private:
ListNode<Object> *header;
public:
List( ){
header = new ListNode<Object>;
}
List( const List & rhs );
~List( ) {
makeEmpty( ); // Get rid of all list nodes
delete header; // then get rid of the header
}
bool isEmpty( ) const{ // see if the header point to NULL
return header->next == NULL;
}
void makeEmpty( ){
while( !isEmpty( ) )
remove( first( ).retrieve( ) );
}
ListItr<Object> zeroth( ) const{
return ListItr<Object>( header );
}
ListItr<Object> first( ) const{
return ListItr<Object>( header->next );
}
void insert( const Object & x, const ListItr<Object> & p ){
if( p.current != NULL )
p.current->next = new ListNode<Object>( x, p.current->next );
}
ListItr<Object> find( const Object & x ) const{
ListNode<Object> *itr = header->next; // Initialize
while( itr != NULL && itr->element != x )
itr = itr->next;
return ListItr<Object>( itr );
}
bool isExist( const Object & x ) const{
ListNode<Object> *itr = header->next; // Initialize
while( itr != NULL){
if(itr->element == x)
return true;
itr = itr->next;
}
return false;
}
ListItr<Object> findPrevious( const Object & x ) const{
ListNode<Object> *itr = header;
while((itr->next != NULL) && itr->next->element != x )
itr = itr->next;
return ListItr<Object>( itr );
}
void remove( const Object & x ){
ListItr<Object> p = findPrevious( x );
if( p.current->next != NULL )
{
ListNode<Object> *oldNode = p.current->next;
p.current->next = p.current->next->next; // Bypass deleted node
delete oldNode;
}
}
const List & operator=( const List & rhs ){
if( this != &rhs )
{
makeEmpty( );
ListItr<Object> ritr = rhs.first( );
ListItr<Object> itr = zeroth( );
for( ; !ritr.isPastEnd( ); ritr.advance( ), itr.advance( ) )
insert( ritr.retrieve( ), itr );
}
return *this;
}
};
#endif
您的標頭為List
模板聲明了一個復制構造函數:
template<class Object>
class List
{
// ...
List( const List & rhs );
但是,此副本構造函數未在任何地方定義。
因此,您的編譯器在編譯此轉換單元時將假定模板實例將在另一個轉換單元中定義並發出外部符號引用。 並且由於沒有在任何地方定義復制構造函數,因此您的程序無法鏈接。
由於缺少模板方法實例化,編譯器報告的錯誤是經典的未定義符號錯誤。
您需要在頭文件中實現並定義此模板的副本構造函數。
您為List
聲明了一個復制構造函數,但沒有實現它:
template <class Object>
class List
{
...
public:
...
List( const List & rhs ); // <-- DECLARATION ONLY!
...
};
鏈接器抱怨找不到List(const List &)
(在復制pages
成員1時,由編譯器生成的Data
復制構造函數調用該實現)。
通常使用副本構造函數來實現副本分配運算符,例如:
template <class Object>
class List
{
...
public:
...
List( const List & src ){
header = new ListNode<Object>;
ListItr<Object> sitr = src.first( );
ListItr<Object> itr = zeroth( );
for( ; !sitr.isPastEnd( ); sitr.advance( ), itr.advance( ) )
insert( sitr.retrieve( ), itr );
}
}
...
List& operator=( const List & rhs ){
if( this != &rhs )
{
List<Object> temp(rhs);
std::swap(temp.header, header);
}
return *this;
}
...
};
1:順便說一句,根本不需要您的Data()
默認構造函數。 std::string
有自己默認的構造函數,所以你的初始化Data::keyword
成員是多余的,並且構造函數聲明一個未使用的本地 List
命名變量pages
是陰影的Data:::pages
成員。 由於List
也具有默認的構造函數,因此無需嘗試顯式初始化Data::pages
成員。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.