【问题标题】:Overloading << and >> as outside member functions for template class [duplicate]重载<<和>>作为模板类的外部成员函数[重复]
【发布时间】:2022-01-16 12:16:53
【问题描述】:

我正在尝试像这样在类外定义我的运算符重载:

template <typename Type>
class myClass
{
    ...
    friend std::ostream& operator << (std::ostream&, const myClass&);
    friend std::istream& operator >> (std::istream&, myClass&);
    ...
}

template <typename Type>
std::ostream& myClass<Type> :: operator << (std::ostream& out, const myClass<Type>& other) { ... }

template <typename Type>
std::istream& myClass<Type> :: operator >> (std::istream& in, myClass<Type>& other) { ... }

我的问题是我收到一条错误消息,说“类模板 class 没有成员 operator”,我不明白这是如何发生的或为什么会发生.

【问题讨论】:

  • 成员函数 != 命名空间范围函数。 myClass 中的 friend 声明用于全局函数,但您正试图将它们实现为成员函数。尝试在实现中删除myClass&lt;Type&gt; ::
  • 另外,你在类声明之后缺少;,但我认为这只是一个复制粘贴错误。
  • 如果我从声明中删除 myClass 它会给我一个链接器错误,是的,复制粘贴错误,忘记了 ;类声明后

标签: c++ templates operator-overloading function-definition friend-function


【解决方案1】:

对于初学者来说,友元函数不是它们被贴花的类的成员函数。

所以这些声明无论如何都是不正确的。

template <typename Type>
std::ostream& myClass<Type> :: operator << (std::ostream& out, const myClass<Type>& other) { ... }

template <typename Type>
std::istream& myClass<Type> :: operator >> (std::istream& in, myClass<Type>& other) { ... } 

其次,在类定义中,您声明了非模板友元函数。

您需要在类定义中提供它们的定义。或者对于类的每个潜在模板参数,您必须在类之外定义友元函数。

这是一个演示程序,展示了如何在类模板定义中定义一个非模板友元函数。

#include <iostream>

template <typename T>
class A
{
private:
    T t;

public:
    A( const T &t ) : t( t ) {}

    friend std::ostream &operator <<( std::ostream &os, const A &a )
    {
        return os << a.t;
    }
};


int main()
{
    std::cout << A<int>( 10 ) << '\n';
    std::cout << A<const char *>( "Hello" ) << '\n';
}

程序输出是

10
Hello

这里有一个演示程序,展示了如何在类模板定义之外定义友元函数。也就是说,对于每个使用的类模板特化,您需要定义非模板友元函数。

#include <iostream>

template <typename T>
class A
{
private:
    T t;

public:
    A( const T &t ) : t( t ) {}

    friend std::ostream &operator <<( std::ostream &os, const A &a );
};


std::ostream &operator <<( std::ostream &os, const A<int> &a )
{
    return os << a.t;
}

std::ostream &operator <<( std::ostream &os, const A<const char *> &a )
{
    return os << a.t;
}

int main()
{
    std::cout << A<int>( 10 ) << '\n';
    std::cout << A<const char *>( "Hello" ) << '\n';
}

另一种方法是声明模板友元函数。例如

#include <iostream>

template <typename T>
class A
{
private:
    T t;

public:
    A( const T &t ) : t( t ) {}

    template <typename T>
    friend std::ostream &operator <<( std::ostream &os, const A<T> &a );
};

template <typename T>
std::ostream &operator <<( std::ostream &os, const A<T> &a )
{
    return os << a.t;
}

int main()
{
    std::cout << A<int>( 10 ) << '\n';
    std::cout << A<const char *>( "Hello" ) << '\n';
}

【讨论】:

  • 我想在课堂之外定义它们,但我似乎无法让它发挥作用。
  • @EpicShadowXD 在类之外定义模板化友元函数有一些微妙之处。内联定义它通常会产生更易读的代码。见overloading friend operator<< for template class
  • @EpicShadowXD 查看我附加的答案。
  • 弗拉德,求求你了,我想让它在外面。上周我一直在这里哭,因为我不能让它在类模板之外工作。我已经让它在里面工作,但我想在外面做,把定义和声明分成两个单独的文件。
  • @Brian 我确实按照大卫罗德里格斯所说的那样做了,我得到一个链接器错误:(((((((((()(((((((((((((((())) (((
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 2016-04-06
相关资源
最近更新 更多