模板上的算术运算符过载,导致无法解析的外部错误
Overloaded arithmetic operators on a template causing an unresolved external error
假设我有这个类:
在Vector4.h中:
#pragma once
template<typename T>
class Vector4
{
public:
T X;
T Y;
T Z;
T W;
Vector4();
Vector4(T X, T Y, T Z, T W);
~Vector4();
friend Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);
};
#include "Vector4.inl"
并且在Vector4.inl中:
template<typename T>
Vector4<T>::Vector4()
{
X = 0;
Y = 0;
Z = 0;
W = 0;
}
template<typename T>
Vector4<T>::Vector4(T X, T Y, T Z, T W)
{
this->X = X;
this->Y = Y;
this->Z = Z;
this->W = W;
}
template<typename T>
Vector4<T>::~Vector4()
{
}
template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r)
{
return(Vector4<T>(l.X * r.X, l.Y * r.Y, l.Z * r.Z, l.W * r.W));
}
当我在这样的地方使用它时:
Vector4<float> a, b;
a = a * b;
它给了我一个LNK2019未解析的外部符号我做错了什么?我使用的语法不正确吗?
如注释所述,您的朋友函数声明
friend Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);
在全局命名空间中声明了一个非模板函数。当您实例化例如Vector4<int>
时,函数
Vector4<int> operator*(const Vector4<int>& l, const Vector4<int>& r)
已声明。请注意,它不是函数模板。(另请参阅[临时朋友])
然后Vector4.inl
声明并定义一个函数模板
template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r)
即前一功能的过载。在表达式a * b
中,重载解析选择非模板operator*
而不是模板版本(请参见[over.match.best]/1)。这会导致链接器错误,因为尚未定义非模板函数。
正如我几乎愚弄了自己一样,一句简短的话:
template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);
由于这个操作符是一个自由函数(非成员函数),这两行声明了一个函数模板,很像
template<typename T>
Vector4<T> wup();
另一方面,
template<typename T>
Vector4<T> Vector4<T>::operator*(const Vector4<T>& r)
{ /* ... */ }
定义类模板(Vector4
)的成员函数(非模板)。
一种解决方案是使用前向声明,只与特定的专业化交朋友:
template<typename T>
class Vector4;
template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);
template<typename T>
class Vector4
{
public:
T X;
T Y;
T Z;
T W;
Vector4();
Vector4(T X, T Y, T Z, T W);
~Vector4();
// compiler knows of some function template `operator*`,
// can name an specialization:
// ~~~~~~~~~~~~~~~~~~~~~~~~vvv
friend Vector4<T> operator*<T>(const Vector4<T>& l, const Vector4<T>& r);
};
template<typename T>
Vector4<T>::Vector4()
{
X = 0;
Y = 0;
Z = 0;
W = 0;
}
template<typename T>
Vector4<T>::Vector4(T X, T Y, T Z, T W)
{
this->X = X;
this->Y = Y;
this->Z = Z;
this->W = W;
}
template<typename T>
Vector4<T>::~Vector4()
{}
template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r)
{
return(Vector4<T>(l.X * r.X, l.Y * r.Y, l.Z * r.Z, l.W * r.W));
}
int main()
{
Vector4<float> a, b;
a = a * b;
}
另一个解决方案是将整个operator*
模板作为朋友,而不是单个专业化:
template<typename U>
friend Vector4<U> operator*(Vector4<U> const&, Vector4<U> const&);
我能够将代码更改为非友好版本:
-
类定义中的代码:
Vector4<T> operator*(Vector4<T> const & r);
-
操作员代码*。它被更改为只接受一个参数。
template<typename T> Vector4<T> Vector4<T>::operator*(Vector4<T> const &r) { return(Vector4<T>(this->X * r.X, this->Y * r.Y, this->Z * r.Z, this->W * r.W)); }
首先从.h文件中的operator*
声明中删除friend
它应该是这样的:
Vector4<T> operator*(const Vector4<T>& r);
然后在.inl文件中,运算符*应该如下所示:
Vector4<T> Vector4<T>::operator*(const Vector4<T>& r){
return(Vector4<T>(X * r.X, Y * r.Y, Z * r.Z, W * r.W));
}
运算符左侧的操作数称为此成员函数。
相关文章:
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- spdlog标头仅与外部fmt一起使用.spdlog错误:'内部':不是'fmt'
- 我收到错误LNK2001:未解析的外部符号(C++代码)
- Visual Studio 2017 中的 QtMetaObject 未解决的外部错误
- 外部"C"拆卸导致奇怪的链接器错误
- C++指针无法在函数外部传递值和分段错误(核心转储)错误
- 在Embarcadero C++ Builder中生成的DLL未解决的外部链接错误
- 可视抽象类 c++(错误 LNK 2001:未解析的外部符号)
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- 当 lib 已添加到其他依赖项时,如何在 VS 中调试未解析的外部符号错误
- 错误LNK2019未解析的外部符号"public: __thiscall SLinkList<char>::SLinkList<char>(void)"
- 外部函数在 main() 上调用时返回分段错误 11.(C++)
- 引入参数化构造函数后显示 LNK 2019 未解析外部符号的代码错误
- 每次我要使用外部资源时,我都会得到:collect2。exe:错误 ld 返回 1 退出状态
- 链接器错误:切换到unicode生成给出:未解析的外部符号WinMain
- C#WPF和C++/CLI以及C++在C++/CLI中添加外部库错误
- 函数 LNK2019 "int __cdecl __scrt_common_main_seh(void)" 中引用的未解析外部符号主错误 (?__scrt_common_main_seh@@YAHXZ
- C++:在"try"外部创建的类型会导致错误,但在内部不会
- 编译错误外部接口Simulink
- 为什么这会给出多个定义错误:外部 int i;国际 i;.