模板 class 的一些友元函数显示未定义的引用
Some friend functions of a template class exhibit undefined reference
最初正在研究其他人之前提出的问题:Why string is not printed?C++。看到 OP 没有充分利用 DataOut
和 GetData
的模板,所以我也尝试将它们设为模板。
这是我最终得到的代码:
#include <iostream>
#include <string>
template<class T>
class Array{
public:
T U[10];
friend void DataOut(const Array&);
friend void GetData(Array&);
};
template<class T>
void DataOut(const Array<T>& arr){
std::cout << arr.U[0];
}
template<class T>
void Getdata(Array<T>& arr){
std::cin >> arr.U[0];
std::cin.clear();
}
int main(){
Array<std::string> Arr1;
Getdata(Arr1);
DataOut(Arr1);
}
但是,我得到了 DataOut
的未定义引用:main.cpp:(.text+0x3a): undefined reference to 'DataOut(Array<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)'
我找到了两种解决方法:
- 定义
DataOut
里面的Array
class.
- 在 main 中调用
DataOut<std::String>
,而不仅仅是 DataOut
。
问题来了,GetData
怎么没有报错呢?我也试过以不同的顺序调用和定义它们,但仍然是相同的结果。
有什么我想念的吗?或者这是我的编译器 (clang 7.0.0
) 的错误?
您声明了两个(的)非模板友元函数
template<class T>
class Array{
public:
T U[10];
friend void DataOut(const Array&);
friend void GetData(Array&);
};
如果您希望这样的非模板函数成为 class 模板特化的友元函数,您必须为该特化显式定义它。
这是一个演示程序。
#include <iostream>
#include <iomanip>
#include <string>
template <typename T>
class A
{
private:
T x = T();
friend void f( const A & );
};
void f( const A<int> &a )
{
std::cout << "a.x = " << a.x << '\n';
}
void f( const A<std::string> &a )
{
std::cout << std::boolalpha << "a.x is empty = " << a.x.empty() << '\n';
}
int main()
{
f( A<int>() );
f( A<std::string>() );
return 0;
}
它的输出是
a.x = 0
a.x is empty = true
例如,如果您将在 main
中添加以下语句
f( A<long>() );
那么编译器会报错,因为没有这样的非模板函数。 class 模板的这种特殊化的函数未定义。
您可以在 class 中定义好友非模板函数。在这种情况下,编译器将为 class 模板的每个特化实例化所谓的模板化实体。
也就是这个函数模板声明
template<class T>
void DataOut(const Array<T>& arr){
std::cout << arr.U[0];
}
与非模板友元函数没有任何共同点DataOut
。
关于这个问题
The question is, how come no errors happens to GetData? I also tried
to call and define them in different orders, but still the same
result.
那么你在 class 和 class 之外的函数命名有一个错字。那就是你有两个不同的函数 GetData
和 Getdata
.
Vlad 回答了我的大部分问题。同时,我想出了如何从一些 gcc 警告中将友元函数定义为模板函数:
template<class T>
class Array; // Forward declaration of the Array<T> class
template<class T>
void DataOut(const Array<T>& arr){
std::cout << arr.U[0];
}
template<class T>
class Array{
public:
T U[10];
friend void DataOut<>(const Array<T>&); // `<>` used right after `DataOut`
}
最初正在研究其他人之前提出的问题:Why string is not printed?C++。看到 OP 没有充分利用 DataOut
和 GetData
的模板,所以我也尝试将它们设为模板。
这是我最终得到的代码:
#include <iostream>
#include <string>
template<class T>
class Array{
public:
T U[10];
friend void DataOut(const Array&);
friend void GetData(Array&);
};
template<class T>
void DataOut(const Array<T>& arr){
std::cout << arr.U[0];
}
template<class T>
void Getdata(Array<T>& arr){
std::cin >> arr.U[0];
std::cin.clear();
}
int main(){
Array<std::string> Arr1;
Getdata(Arr1);
DataOut(Arr1);
}
但是,我得到了 DataOut
的未定义引用:main.cpp:(.text+0x3a): undefined reference to 'DataOut(Array<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)'
我找到了两种解决方法:
- 定义
DataOut
里面的Array
class. - 在 main 中调用
DataOut<std::String>
,而不仅仅是DataOut
。
问题来了,GetData
怎么没有报错呢?我也试过以不同的顺序调用和定义它们,但仍然是相同的结果。
有什么我想念的吗?或者这是我的编译器 (clang 7.0.0
) 的错误?
您声明了两个(的)非模板友元函数
template<class T>
class Array{
public:
T U[10];
friend void DataOut(const Array&);
friend void GetData(Array&);
};
如果您希望这样的非模板函数成为 class 模板特化的友元函数,您必须为该特化显式定义它。
这是一个演示程序。
#include <iostream>
#include <iomanip>
#include <string>
template <typename T>
class A
{
private:
T x = T();
friend void f( const A & );
};
void f( const A<int> &a )
{
std::cout << "a.x = " << a.x << '\n';
}
void f( const A<std::string> &a )
{
std::cout << std::boolalpha << "a.x is empty = " << a.x.empty() << '\n';
}
int main()
{
f( A<int>() );
f( A<std::string>() );
return 0;
}
它的输出是
a.x = 0
a.x is empty = true
例如,如果您将在 main
中添加以下语句f( A<long>() );
那么编译器会报错,因为没有这样的非模板函数。 class 模板的这种特殊化的函数未定义。
您可以在 class 中定义好友非模板函数。在这种情况下,编译器将为 class 模板的每个特化实例化所谓的模板化实体。
也就是这个函数模板声明
template<class T>
void DataOut(const Array<T>& arr){
std::cout << arr.U[0];
}
与非模板友元函数没有任何共同点DataOut
。
关于这个问题
The question is, how come no errors happens to GetData? I also tried to call and define them in different orders, but still the same result.
那么你在 class 和 class 之外的函数命名有一个错字。那就是你有两个不同的函数 GetData
和 Getdata
.
Vlad 回答了我的大部分问题。同时,我想出了如何从一些 gcc 警告中将友元函数定义为模板函数:
template<class T>
class Array; // Forward declaration of the Array<T> class
template<class T>
void DataOut(const Array<T>& arr){
std::cout << arr.U[0];
}
template<class T>
class Array{
public:
T U[10];
friend void DataOut<>(const Array<T>&); // `<>` used right after `DataOut`
}