在模板重载算术运算符导致无法解析的外部错误(Overloaded arithmetic operat

2019-09-29 05:34发布

比方说,我有这个类:

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解析的外部符号我在做什么错?是语法我使用的是不正确的?

Answer 1:

正如评论所说,你的朋友函数声明

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)

声明。 请注意,这不是一个函数模板。 (也见[temp.friend])

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&);


Answer 2:

我能够更改代码以nonfriended版本:

  1. 类定义中的代码:

     Vector4<T> operator*(Vector4<T> const & r); 
  2. 运算符*的代码。 它更改为只需要一个参数。

     template<typename T> Vector4<T> Vector4<T>::operator*(Vector4<T> const &r) { return(Vector4<T>(this->X * rX, this->Y * rY, this->Z * rZ, this->W * rW)); } 


Answer 3:

首先,删除friend从您的声明operator*在.h文件

它应该是这样的:

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));
}

对操作人员的左侧的操作数是什么所谓的这个成员函数。



文章来源: Overloaded arithmetic operators on a template causing an unresolved external error