当前位置: 首页 > 知识库问答 >
问题:

模板类中的朋友函数

华坚成
2023-03-14

我试图使乘法运算符成为名为TVector3的模板类的朋友。我读过,我可以在类声明中声明朋友函数之前,对其进行前向声明,但我这样做的尝试是徒劳的。我知道我可以简单地定义friend函数而不是声明它,但我希望它能与前向声明技术一起工作。

特别是,我试图为我的案例实施这个解决方案。我发现这篇文章也是David Rodriguez给出的解决方案(第三个版本),但我不知道我做错了什么。

我使用'g template.cpp tempmain.cpp a'进行编译,编译器(g)给出了以下错误:

未定义引用射线::TVector3射线::运算符*(浮点,射线::TVector3 const

对于以下代码:

模板. h:

#ifndef TVECTOR_H
#define TVECTOR_H

#include <cmath>

namespace ray
{
    //forward declarations
    template <class T> class TVector3;
    template <class T> TVector3<T> operator* (T, const TVector3<T> &);

    template <class T>
    class TVector3 {

        public:
            union {
                struct {
                    T x, y, z;
                };
                T xyz[3];
            };

        //function needed
        friend TVector3<T> operator*<T> (T, const TVector3<T> &);
    };

}

#endif

template.cpp:

#include "template.h"

using namespace ray;

//friend operator function
template<class T> TVector3<T> operator * (T f, const TVector3<T> &v)
{
    return TVector3<T>(f * v.x, f * v.y, f * v.z);
}

//instantiate template of type float
template class TVector3<float>;

tempmain.cpp:

#include <iostream>
#include "template.h"

int main()
{
    ray::TVector3<float> v1, v2;

    v2.x = 3;
    v1 = 4.0f * v2; //this reports as undefined

    std::cout << v1.x << "\n";

    return 0;
}

这是完整的源代码。我做错了什么?

共有2个答案

百里诚
2023-03-14

您应该显式实例化运算符*,它的工作方式如下

using namespace ray;

//friend operator function
template<class T> TVector3<T> ray::operator * (T f, const TVector3<T> &v)
{
    return TVector3<T>(f * v.x, f * v.y, f * v.z);
}

//instantiate template of type float
template class TVector3<float>;
template TVector3<float> ray::operator*<float>( float, TVector3<float> const& );

请记住,如果您编写运算符*代替ray::运算符*编译器无法知道您的意思是ray::运算符*并且您没有在全局命名空间中声明新运算符!

不要忘记定义TVector3(T x_,T y_,T z_):)

徐洋
2023-03-14

一般来说,模板应该在标题中定义。如果在cpp文件中定义了它们,则需要手动实例化模板。您正在为类模板执行此操作,但没有实例化运算符*模板。

template TVector3<T> operator*<T> (T, const TVector3<T> &);

此外,我建议您不要使用模板化的< code >操作符*,而是通过在类模板中声明和定义非模板自由函数:

template <class T>
class TVector3 {
//function needed
    friend TVector3<T> operator*(T f, const TVector3<T> & v) {
       return TVector3<T>(f * v.x, f * v.y, f * v.z);
    }
};

这具有免费函数(它允许第一个参数的转换)和模板(它将按需生成免费函数——即不需要手动提供所有实现)以及有限可见性(它只能通过ADL查找)的优点

 类似资料:
  • 我无法让它工作: 无法编译,错误消息如下: 无效使用temping-id'运算符*

  • 我有一个模板,其中有一个friend函数的声明,在类之外,我有它的实现: 在其他文件中的某个地方将其命名为什么签名? 我尝试过: 但它说它无法解决这个问题。为什么?朋友成员应该这样看待,不是吗? 编辑: 这是在Troll.cpp在它的功能。 仍会喊出“未在此范围内声明”、“函数无法解析”、“符号无法解析”、“之前应为主表达式”、“之前应为主表达式”

  • 我正在学习一个视频教程,我想声明一个模板函数作为模板类的朋友。我不知道为什么代码会抛出错误。 编译器抛出错误。 错误: templates\u friends\u 38。cpp:在“void doSomething2(T)[T=int]”的实例化中:templates\u friends\u 38。cpp:40:19:此处需要templates\u friends\u 38。cpp:32:9:错误

  • 我的C++代码示例中有一个很大的问题。“朋友”和“模板”有问题。 错误消息: Matrix.h:26:79:警告: 友元声明'std::oStream&MatrixClass::Operator<<(std::oStream&,const MatrixClass::Matrix&)'声明一个非模板函数[-wnon-template-friend]友元声明'std::oStream&Operator

  • 我想知道如果函数的模板参数包括但不限于类的模板参数,如何使函数成为类的朋友并在类外定义函数。 例如,我有以下模板类和模板朋友函数: 如果我编译: 我会得到以下链接器错误:

  • 为了了解在朋友关系中使用Neo4J的优势,我在MySQL数据库上创建了一个Persons表(“Persons”,20900个数据集): 和一张关系表(“友谊”,每个人有50到100个朋友): 因此,大约有120万人的关系。 现在我想查看id=1的人的朋友的朋友的朋友的朋友,因此我创建了一个如下查询: 用户ID 1的查询用了大约30秒 在Neo4J中,我为每个人创建了一个节点(20900个节点)和一