您的代码片段有两个问题。
The 第一个问题是您将实现放在源文件而不是头文件中。因此,要解决这个问题,只需将实现移至头文件中即可。
The 第二个问题即使您将实现移至源文件中,程序仍然无法工作(Demo)。这是因为朋友宣言您目前拥有的(对于超载的opearator<<
),是对于一个普通(非模板)函数。也就是说,在你的原始代码中operator<<
用于类模板Property<>
不是函数模板,而是在需要时使用类模板实例化的“普通”函数。这就是我们所说的模板化实体.
But the 定义您在源文件(.cpp)中为重载运算符 std::cout << num << "\n";链接器找不到普通重载对应的定义/实现operator<<
你有朋友声明。
有两种方法可以解决这个问题:
Method 1
在友元声明中添加单独的参数子句。
template <class PropertyType>
class Property {
PropertyType m_property;
public:
const PropertyType& operator=(const PropertyType& value);
template<typename T> //parameter cluase added here
//---------------------------------------------------vvvvv----------------------->const added here
friend std::ostream& operator<<(std::ostream& os,const Property<T>& other);
};
template <class PropertyType>
//----------------------------------------vvvvv---------------------------------->const added here
std::ostream& operator<<(std::ostream& os,const Property<PropertyType>& other) {
os << other.m_property;
return os;
}
Demo
Method 2
这里我们为重载提供前向声明operator<<
.
//forward declaration for class template Property
template<typename T> class Property;
//forward declaration for overloaded operator<<
template<typename T> std::ostream& operator<<(std::ostream&,const Property<T>&);//note the const in the second parameter
template <class PropertyType>
class Property {
PropertyType m_property;
public:
const PropertyType& operator=(const PropertyType& value);
//---------------------------------vvvvvvvvvvvvvv---------------------------------> angle brackets used here
friend std::ostream& operator<<<PropertyType>(std::ostream& os,const Property<PropertyType>& other);//also note the const in the second parameter
};
template <class PropertyType>
const PropertyType& Property<PropertyType>::operator=(const PropertyType& value) {
m_property = value;
return m_property;
}
template <class PropertyType>
//----------------------------------------vvvvv---------------------------------->const added here
std::ostream& operator<<(std::ostream& os,const Property<PropertyType>& other) {
os << other.m_property;
return os;
}
Demo
Method 3
如果您想在源文件而不是头文件中提供实现,那么您应该添加
template std::ostream& operator<<(std::ostream& os, Property<int>& other);
在源文件中除了为友元声明添加模板参数子句之外,如下所示:
class.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
template <class PropertyType>
class Property {
PropertyType m_property;
public:
const PropertyType& operator=(const PropertyType& value);
template<typename T> //parameter clause added
//---------------------------------------------------vvvvv--------------------->const added here
friend std::ostream& operator<<(std::ostream& os,const Property<T>& other);
};
#endif
类.cpp
#include "class.h"
template <class PropertyType>
const PropertyType& Property<PropertyType>::operator=(const PropertyType& value) {
m_property = value;
return m_property;
}
template<typename PropertyType>
//----------------------------------------vvvvv------->const added here
std::ostream& operator<<(std::ostream& os,const Property<PropertyType>& other) {
os << other.m_property;
return os;
}
template class Property<int>;
template std::ostream& operator<<(std::ostream& os,const Property<int>& other);
main.cpp
#include <iostream>
#include "class.h"
int main() {
Property<int> num;
num = 100;
std::cout << num << "\n";
}
Demo
我所做的改变包括:
-
为友元声明添加了单独的模板参数子句。这是因为友元声明是针对函数模板的。此外,我们指定了一个不同的类型参数,名为T
并不是PropertyType because otherwise the new
财产种类will shadow the outer
属性类型`.
-
添加了低级const
重载的第二个参数opeartor<<
.
-
在方法3中,在源文件(class.cpp)中,添加
template std::ostream& operator<<(std::ostream& os,const Property<int>& other);
对于非成员函数重载operator<<
.