[answer]
将模板类中关于友元函数的声明更改为:
template<class ItemType>
class GenericList
{
public:
GenericList(int max);
~GenericList();
int length() const;
void add(ItemType new_item);
bool full() const;
void erase();
template<class ItemType1> friend ostream& operator << (ostream& outs,const GenericList<ItemType1>& the_list);
private:
ItemType * item;
int max_length;
int current_length;
};
[Question]
我在看 Walter Savitch的 《C++面向对象程序设计第7版》的模板类那一节时,例子程序运行出错。哪位大侠能帮我看看啊?
错误信息如下:
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# g++ main.cpp -o main.o
In file included from main.cpp:2:0:
genericlist.h:18:88: warning: friend declaration ‘std::ostream& listsavitch::operator<<(std::ostream&, const listsavitch::GenericList<ItemType>&) declares a non-template function [-Wnon-template-friend]
genericlist.h:18:88: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/ccFUMtfR.o: In function `main':
main.cpp:(.text+0x56): undefined reference to `listsavitch::operator<<(std::basic_ostream<char, std::char_traits<char> >&, listsavitch::GenericList<int> const&)'
main.cpp:(.text+0xb8): undefined reference to `listsavitch::operator<<(std::basic_ostream<char, std::char_traits<char> >&, listsavitch::GenericList<char> const&)'
collect2: ld returned 1 exit status
代码源文件如下:
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# ls
genericlist.cpp genericlist.h main.cpp
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# vim genericlist.h
#ifndef GENERICLIST_H
#define GENERICLIST_H
#include <iostream>
using namespace std;
namespace listsavitch
{
template<class ItemType>
class GenericList
{
public:
GenericList(int max);
~GenericList();
int length() const;
void add(ItemType new_item);
bool full() const;
void erase();
friend ostream& operator <<(ostream& outs,const GenericList<ItemType>& the_list);
private:
ItemType * item;
int max_length;
int current_length;
};
} //listsavitch
#endif //LIST_H
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# vim genericlist.cpp
#ifndef GENERICLIST_CPP
#define GENERICLIST_CPP
#include <iostream>
#include <cstdlib>
#include "genericlist.h"
using namespace std;
namespace listsavitch
{
//use cstdlib;
template<class ItemType>
GenericList<ItemType>::GenericList(int max) : max_length(max),current_length(0)
{
item=new ItemType[max];
}
template<class ItemType>
GenericList<ItemType>::~GenericList()
{
delete [] item;
}
template<class ItemType>
int GenericList<ItemType>::length() const
{
return (current_length);
}
template<class ItemType>
void GenericList<ItemType>::add(ItemType new_item)
{
if(full())
{
cout << "Error: adding to a full list.\n";
exit(1);
}
else
{
item[current_length]=new_item;
current_length=current_length+1;
}
}
template<class ItemType>
bool GenericList<ItemType>::full() const
{
return (current_length==max_length);
}
template<class ItemType>
void GenericList<ItemType>::erase()
{
current_length=0;
}
template<class ItemType>
ostream& operator <<(ostream& outs,const GenericList<ItemType>& the_list)
{
for(int i=0;i<the_list.current_length;i++)
outs << the_list.item[i] << endl;
return outs;
}
}
#endif
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# vim main.cpp
#include <iostream>
#include "genericlist.h"
#include "genericlist.cpp"
using namespace std;
using namespace listsavitch;
int main()
{
GenericList<int> first_list(2);
first_list.add(1);
first_list.add(2);
cout << "first_list = \n"
<< first_list;
GenericList<char> second_list(10);
second_list.add('A');
second_list.add('B');
second_list.add('C');
cout << "second_list = \n"
<< second_list;
return 0;
}
错误信息如下:
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# g++ main.cpp -o main.o
In file included from main.cpp:2:0:
genericlist.h:18:88: warning: friend declaration ‘std::ostream& listsavitch::operator<<(std::ostream&, const listsavitch::GenericList<ItemType>&) declares a non-template function [-Wnon-template-friend]
genericlist.h:18:88: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/ccFUMtfR.o: In function `main':
main.cpp:(.text+0x56): undefined reference to `listsavitch::operator<<(std::basic_ostream<char, std::char_traits<char> >&, listsavitch::GenericList<int> const&)'
main.cpp:(.text+0xb8): undefined reference to `listsavitch::operator<<(std::basic_ostream<char, std::char_traits<char> >&, listsavitch::GenericList<char> const&)'
collect2: ld returned 1 exit status
代码源文件如下:
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# ls
genericlist.cpp genericlist.h main.cpp
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# vim genericlist.h
#ifndef GENERICLIST_H
#define GENERICLIST_H
#include <iostream>
using namespace std;
namespace listsavitch
{
template<class ItemType>
class GenericList
{
public:
GenericList(int max);
~GenericList();
int length() const;
void add(ItemType new_item);
bool full() const;
void erase();
friend ostream& operator <<(ostream& outs,const GenericList<ItemType>& the_list);
private:
ItemType * item;
int max_length;
int current_length;
};
} //listsavitch
#endif //LIST_H
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# vim genericlist.cpp
#ifndef GENERICLIST_CPP
#define GENERICLIST_CPP
#include <iostream>
#include <cstdlib>
#include "genericlist.h"
using namespace std;
namespace listsavitch
{
//use cstdlib;
template<class ItemType>
GenericList<ItemType>::GenericList(int max) : max_length(max),current_length(0)
{
item=new ItemType[max];
}
template<class ItemType>
GenericList<ItemType>::~GenericList()
{
delete [] item;
}
template<class ItemType>
int GenericList<ItemType>::length() const
{
return (current_length);
}
template<class ItemType>
void GenericList<ItemType>::add(ItemType new_item)
{
if(full())
{
cout << "Error: adding to a full list.\n";
exit(1);
}
else
{
item[current_length]=new_item;
current_length=current_length+1;
}
}
template<class ItemType>
bool GenericList<ItemType>::full() const
{
return (current_length==max_length);
}
template<class ItemType>
void GenericList<ItemType>::erase()
{
current_length=0;
}
template<class ItemType>
ostream& operator <<(ostream& outs,const GenericList<ItemType>& the_list)
{
for(int i=0;i<the_list.current_length;i++)
outs << the_list.item[i] << endl;
return outs;
}
}
#endif
root@xiaoy-ProLiant:/home/xiaoy/sample/Class_Template# vim main.cpp
#include <iostream>
#include "genericlist.h"
#include "genericlist.cpp"
using namespace std;
using namespace listsavitch;
int main()
{
GenericList<int> first_list(2);
first_list.add(1);
first_list.add(2);
cout << "first_list = \n"
<< first_list;
GenericList<char> second_list(10);
second_list.add('A');
second_list.add('B');
second_list.add('C');
cout << "second_list = \n"
<< second_list;
return 0;
}