如何为模板类重载%运算符?

时间:2017-05-29 04:41:25

标签: c++ class templates overloading operator-keyword

我创建了一个模板类Number。我重载了<<运营商,但我无法让%运营商工作。

template<typename t>
class Number
{
private:
    t n;
public:
    Number(t a) :n{ a } {};
    Number() :n{ t() } {};
    friend ostream & operator<<<>(ostream & os, const Number<t>& a);
    friend Number<t> operator%(Number<t> a, Number<t> b);
};
template<typename t>
ostream & operator<<<>(ostream & os, Number<t> a)
{
    os << a.n;
    return os;
}
template<typename t> 
Number<t> operator%(Number<t> a, Number<t> b)
{
    return Number<t>(a.n % b.n);
}

正如您所见&lt;&gt; in&lt;&lt;运算符定义,为它完成工作。但是,如果我在%运算符定义中使用它,我会得到一个语法错误,如果我不这样做 “1未解决的外部”错误。所以我的问题可以归结为两个问题 - 1.为什么我们需要使用&lt;&gt;使用朋友符号重载操作符? 2.为什么它不能用于%运算符?

4 个答案:

答案 0 :(得分:4)

方法1

在类模板的定义之前声明函数。

public static void main(String[] args) {
    int[] p = {7,5,3,1,3,5,7};

    for (int i=0; i <= 7; i++) {
        System.out.print("\n");
        for (int k =i; k <= 7; k++) {
             k = p[i];  
             // I'm trying to find a way to print "*"s with array element value
             for(int j=i; j <= 7; j++) {
                 System.out.print("*");
             }
        }
    }
}

定义班级。确保template <typename t> class Number; template <typename t> std::ostream & operator<<(std::ostream & os, const Number<t>& a); template <typename t> Number<t> operator%(Number<t> a, Number<t> b); 声明使用模板参数。

friend

实现类定义之外的函数。

template <typename t>
class Number
{
private:
    t n;
public:
    Number(t a) :n{ a } {};
    Number() :n{ t() } {};

    // This makes sure that operator<< <int> is a friend of Number<int>
    // but not of Number<double>
    friend std::ostream & operator<< <t>(std::ostream & os, const Number& a);
    friend Number operator%<t>(Number a, Number b);
};

http://ideone.com/dx3fC0处的工作代码。

方法2

在类模板定义中实现template <typename t> std::ostream & operator<<(std::ostream & os, const Number<t>& a) { os << a.n; return os; } template <typename t> Number<t> operator%(Number<t> a, Number<t> b) { return Number(a.n % b.n); } 函数。

friend

http://ideone.com/5PYQnR处的工作代码。

如果template <typename t> class Number { private: t n; public: Number(t a) :n{ a } {}; Number() :n{ t() } {}; friend std::ostream& operator<<(std::ostream & os, const Number& a) { os << a.n; return os; } friend Number operator%(Number a, Number b) { return Number<t>(a.n % b.n); } }; 函数不是太复杂,最好使用第二种方法。整体代码结构很简单。如果friend函数很复杂,那么使用第一种方法并在类定义之外实现它们可能是有意义的。

答案 1 :(得分:1)

在类中“与它交友”之前,您应首先将运算符声明为函数模板。有关如何正确执行此操作的详细信息,请参阅thisthis

我怀疑你operator <<离开的原因是using namespace std未在您的问题中显示,它会从operator <<引入模板<iostream>声明。

这应该有效:

#include <iostream>

template<typename T>
class Number;

// Declare the operators here.
template<typename T>
std::ostream & operator<<(std::ostream & os, const Number<T>& a);

template<typename T>
Number<T> operator%(Number<T> a, Number<T> b);

template<typename T>
class Number
{
private:
    T n;
public:
    Number(T a) :n{ a } {};
    Number() :n{ T() } {};

    friend std::ostream & operator<< <T>(std::ostream & os, const Number& a);

    friend Number operator% <T>(Number a, Number b);
};

template<typename T>
std::ostream & operator<<(std::ostream & os, const Number<T>& a /* was Number<T> ==> signature mismatch */) 
{
    os << a.n;
    return os;
}

template<typename T> 
Number<T> operator%(Number<T> a, Number<T> b)
{
    return Number<T>(a.n % b.n);
}

int main() {
    Number<int> a(5);
    Number<int> b(6);
    auto c = a % b;
    std::cout << a << std::endl;
    return 0;
}

答案 2 :(得分:0)

在课堂体中定义这些功能,省去麻烦。此外,如果%的左侧操作数为Number,则您不必将其设为好友。

#include <iostream>

using std::ostream;

template<typename t>
class Number
{
private:
    t n;
public:
    Number(t a) :n{ a } {};
    Number() :n{ t() } {};

    Number operator%(Number rhs)
    {
        return Number(n % rhs.n);
    }

    friend ostream & operator<<(ostream & os, Number a)
    {
       os << a.n;
       return os;
    }
};


int main()
{
  Number<int> n1(4);
  Number<int> n2(2);

  std::cout << n1 << ' ' << n2 << '\n';

  Number<int> n3 = n1 % n2;
  std::cout << n3 << '\n';
}

答案 3 :(得分:0)

你可以让朋友操作员成为模板化操作员:

template<typename t>
class Number
{
private:
    t n;
public:
    Number(t a) :n ( a ){};
    Number() :n( t() ) {};

    template<typename TT>
    friend Number<TT> operator%(Number<TT> a,const Number<TT>& b);
};

template<typename t> 
Number<t> operator%(Number<t> a,const Number<t> &b)
{
    return Number<t>(a.n % b.n);
}


int _tmain(int argc, _TCHAR* argv[])
{
    Number<int> a;
    Number<int> b;

    Number<int> c = a %b;
    return 0;
}

参见关于外向宣言here的解释。