C ++模板类的朋友操作符重载

时间:2012-08-01 23:22:13

标签: c++ templates operator-overloading friend

我正在尝试创建一个通用的向量类,既可以用于我自己的代码段库,也可以用模板化的类进行练习。从本质上讲,Vector类是模板化的,允许您选择其精度是float,double,long double等。

我遇到的问题是重载*运算符以缩放向量。排除所有工作重载和成员函数后,类定义如下所示:

#pragma once

#include <math.h>   //  for sqrt function when normalizing

template <typename T> class Vector;
template <typename T> Vector<T> operator*(const Vector<T>& obj);

template <typename T> class Vector {
private:
    //  Attributes:
    static const int DIMS = 3;
    T component[DIMS];

public:
    enum { 
        X, Y, Z
    };

public:
    //  Constructors:
    Vector(void) {
        for (int i=0; i<DIMS; ++i) {
            component[i] = T();
        }
    }
    Vector(T x, T y, T z) {
        component[X] = x;
        component[Y] = y;
        component[Z] = z;
    }

    //  Destructor:
    ~Vector(void) { }

    //  Scaling:
    friend Vector<T> operator*(const Vector<T>& obj);
    Vector operator*(const T scale) {
        Vector<T> result = Vector<T>();

        for (int i=0; i<DIMS; ++i) {
            result.component[i] = component[i] * scale;
        }

        return result;
    }
};

template <typename T>
Vector<T> operator*(const Vector<T>& obj) {
    Vector<T> result = Vector<T>();

    for (int i=0; i<DIMS; ++i) {
        result.component[i] = obj.component[i] * this*;
    }

    return result;
}

在我的主要方法中,我有以下几行代码:

Vector<float> testVector1 = Vector<float>(1.0f, 0.0f, 0.0f);
Vector<float> testVector2 = Vector<float>(0.0f, 1.0f, 0.0f);
Vector<float> testVector3 = 10.0f * testVector1;
Vector<float> testVector4 = testVector2 * 10.0f;

除了一个错误外,所有内容都编译正常:当main()中的第四行正常工作(将矢量乘以标量)时,第三行(将标量乘以向量)会给出错误:

Error 1 error C2677: binary '*' : no global operator found which takes type 'Vector<T>' (or there is no acceptable conversion)

我对这个问题的最好猜测是,编译器不知道我正在尝试重载哪个基元的*运算符,而且我不能直接告诉它,因为类在传递到类之前不会知道类型。模板。有没有办法完成我正在尝试做的事情,或者模板是否必须始终跟随类进行运算符重载?

更新 因此,由于jwismar和其他人,我抓住了左手超载的糟糕尝试。现在,类中函数的定义是:

friend Vector<T> operator*(T scalar, const Vector<T>& obj);

它的实施是:

template <typename T> 
Vector<T> operator*(T scalar, const Vector<T>& obj) {
    Vector<T> result = Vector<T>();

    for (int i=0; i<DIMS; ++i) {
        result.component[i] = obj.component[i] * scalar;
    }

    return result;
}

类上面的重载的初始声明现在是template <typename T> Vector<T> operator*(T scalar, const Vector<T>& obj);,但无论它是否被注释掉,我都会得到相同的错误。

现在,我正在讨论有关模板和运算符重载的更具体的问题。编译器现在编译,但错误现在是一个未解析的外部:

Error 1 error LNK2019: unresolved external symbol "class Vector<float> __cdecl operator*(float,class Vector<float> const &)" (??D@YA?AV?$Vector@M@@MABV0@@Z) referenced in function _main C:\Users\D03457489\Desktop\UVCTester\UVCTester\main.obj UVCTester

所以编译器告诉我它可以找到operator*(float, Vector<float>)的定义但是找不到实现。所以新的问题是:是我的另一个基本监督的结果,还是不可能以这种方式使用模板来生成操作数的左侧未知的运算符重载?

3 个答案:

答案 0 :(得分:1)

这不是第4行有错误,它是第3行。编译器正在寻找一个内置的,它在左侧有一个浮点数,而且找不到它。您将需要定义一个自由函数,如:

template <typename T> Vector<T> operator*(T scalar, const Vector<T>& obj);

答案 1 :(得分:0)

尝试使用此功能签名(未经测试):

template <typename T, typename F>
Vector<T> operator*(const F &lhs, const Vector<T>& rhs);

应该允许这样的陈述:

auto vec = f * other_vec;

对于任何类型F,其具有类型的已定义运算符:

template <typename F, typename T>
undetermined operator*(const F& lhs, const T &rhs);

其中TVector<T>使用的类型,返回的类型可以隐式转换为T

所以以下内容可能会奏效:

long l;
float f;
int i;
//.......

Vector<float> v1;
v2 = l * v1;
v3 = f * v2;
v4 = i * v3;

答案 2 :(得分:0)

您需要定义一个允许*的LHS上的标量的函数。幸运的是,这相对容易实现:

template <typename T>
Vector<T> operator*(const T scale, const Vector<T> &v) {
    Vector<T> result = v;
    return result * scale;
}

在两个Vector之间进行组件明智乘法的其他函数未正确声明和实现。它不需要是朋友:

/*friend*/ Vector<T> operator*(const Vector<T>& obj);

然后将其实现为类的方法:

template <typename T>
Vector<T> Vector<T>::operator*(const Vector<T>& obj) {
    Vector<T> result = Vector<T>();

    for (int i=0; i<DIMS; ++i) {
        result.component[i] = obj.component[i] * component[i];
    }

    return result;
}