5

我正在尝试使用友元函数来重载 << 和模板以熟悉模板。我不知道这些编译错误是什么:

Point.cpp:11: error:  shadows template parm 'class T'
Point.cpp:12: error: declaration of 'const Point<T>& T'

对于这个文件

#include "Point.h"

template <class T>
Point<T>::Point() : xCoordinate(0), yCoordinate(0)
{}

template <class T>
Point<T>::Point(T xCoordinate, T yCoordinate) : xCoordinate(xCoordinate), yCoordinate(yCoordinate)
{}

template <class T>
std::ostream &operator<<(std::ostream &out, const Point<T> &T)
{
    std::cout << "(" << T.xCoordinate << ", " << T.yCoordinate << ")";
    return out;
}

我的标题看起来像:

#ifndef POINT_H
#define POINT_H

#include <iostream>

template <class T>
class Point
{
public:
    Point();
    Point(T xCoordinate, T yCoordinate);
    friend std::ostream &operator<<(std::ostream &out, const Point<T> &T);

private:
    T xCoordinate;
    T yCoordinate;
};

#endif

我的标题也给出了警告:

Point.h:12: warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Point<T>&)' declares a non-template function

我也不确定为什么。有什么想法吗?谢谢。

4

3 回答 3

3

模板参数和函数参数具有相同的名称。将其更改为:

template <class T>
std::ostream &operator<<(std::ostream &out, const Point<T> &point)
{
    std::cout << "(" << point.xCoordinate << ", " << point.yCoordinate << ")";
    return out;
}

标头中友元函数的声明也应更改:

template <class G>
friend std::ostream &operator<<(std::ostream &out, const Point<G> &point);
于 2010-06-03T06:59:19.987 回答
1

@Firas 已经回答了您的第一个问题,所以我不会在这里重复。

对于您的第二个问题,它警告您:

friend std::ostream &operator<<(std::ostream &out, const Point<T> &T);

此声明位于类模板中:

template <class T>
class Point { // ...

它告诉您,即使您可以实例化Point许多不同的类型,但您是在说模板operator<<是所有类型的朋友。即,即使存在一组可能无限的不同类型的Points,您已经说过它们只有一个 operator<<

实际上,这似乎是您的代码中的一个错误-您已将其定义 operator<<为函数模板,但将(非模板)函数声明为该类的友元(您的代码似乎未定义该函数) . IOW,这个定义:

template <class T>
std::ostream &operator<<(std::ostream &out, const Point<T> &T)

...是一个模板,这您在上面的朋友声明中指出的不同(尽管我认为您希望它们匹配)。

于 2010-06-03T07:08:24.497 回答
0

您在这里有一个微妙的错误(不相关):模板方法的定义最好放在标题中,因为它们应该(通常)对调用者可见。

对于您的编译问题:正如警告所说,您正在尝试声明一个非模板友元函数。如果你纠正它,那么问题就会神奇地解决。

template <class T>
class Point
{
public:
  template <class U>
  friend std::ostream& operator<<(std::ostream& out, const Point<T>& p);
};

但真正的问题是你需要在friend这里声明吗?当然公众可以访问xy坐标(至少在只读模式下)?

// Free functions
template <class T>
std::ostream& operator<<(std::ostream& out, const Point<T>& p)
{
  return out << '(' << p.x() << ", " << p.y() << ')';
}

最后,请注意,如果您的参数具有与范围内的类型不同的名称,尤其是您使用template语法声明的类型,那将是最好的。

于 2010-06-03T07:13:28.353 回答