我遇到了错误
的问题错误LNK2019未解析的外部符号“class std :: basic_ostream>& __cdecl cop4530 :: operator<<(class std :: basic_ostream>&,class rob :: Stack const&)”(?? 6rob @@ YAAAV?$ basic_ostream @ DU?$ char_traits @ D @ std @@@ std @@ AAV12 @ ABV?$ Stack @ H @ 0 @@ Z)在函数_main Project7中引用c:\ Users \ Robrik \ documents \视觉工作室2015 \ Projects \ Project7 \ Project7 \ post.obj 1
现在,post
正在做的就是调用operator<<
声明
namespace rob {
template < typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
private:
std::vector<T> arr;
};
定义
template < typename T>
inline std::ostream & rob::operator<<(std::ostream & os, const Stack<T>& a) {
return a.print(os, ' ');
}
template<typename T>
inline void rob::Stack<T>::print(std::ostream & os, char c) const
{
for (int i = 0; i != arr.size(); i++)
{
os << c << arr[i];
}
os << '\n';
}
它们分别位于.h
文件和.hpp
中,我要求运算符不是成员函数(用于赋值)。
答案 0 :(得分:3)
代码示例的问题;
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
是否operator<<
被声明为非模板函数。对于T
使用的每种Stack
类型,都需要有非模板operator<<
。例如,如果声明了类型Stack<int>
,那么必须有如下的运算符实现;
std::ostream& operator<< (std::ostream& os, const Stack<int>& a) {/*...*/}
由于未实现,链接器无法找到它并导致错误。
作为旁注; gcc警告如下
warning: friend declaration 'std::ostream& operator<<(...)' declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
这可能不是预期的,每个瞬间原子都有自己的实现。
要更正此问题,您可以在Stack
类型之前声明模板运算符,然后声明为朋友,即实例化。语法看起来有点尴尬,但看起来如下;
// forward declare the Stack
template <typename>
class Stack;
// forward declare the operator <<
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&);
template <typename T>
class Stack {
friend std::ostream& operator<< <>(std::ostream& os, const Stack<T>& a);
// note the required <> ^^^^
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&)
{
// ... implement the operator
}
上面的代码限制了运算符与Stack
的相应实例化的友谊,即operator<< <int>
实例化仅限于访问Stack<int>
实例化的私有成员。
替代方案包括允许友谊扩展到模板的所有实例化;
template <typename T>
class Stack {
template <typename T1>
friend std::ostream& operator<<(std::ostream& os, const Stack<T1>& a);
// ...
};
operator<<
的实现可以在类定义内部或内部完成。
答案 1 :(得分:1)
你还应该在它真正属于的rob命名空间内声明函数签名:
namespace rob {
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
};
template < typename T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a){
...
}
答案 2 :(得分:0)
除了@ LibertyPaul的回答,您需要向朋友template<T>
行添加std::os...
,以便工作:
namespace rob {
template <typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a) {
return a.arr.print(os, ' ');
}
};
}