簡體   English   中英

運算符重載為好友函數

[英]operator overloading as a friend function

我創建了一個模板類,並想重載一個運算符+(幾次)。 我以以下方式進行

template <typename T> class Polynomial;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

....

template <typename T>
class Polynomial {
    ....

    public:

    ....

    Polynomial operator +(const Polynomial& other) const {
       // impelementation
    }

    friend const Polynomial<T> operator + <> (const Polynomial<T>& poly, const T& scalar);

};

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
    // implementation
}

但是,出現以下錯誤(與以“ friend”開頭的行相對應)

problem2.cpp:282:45: error: declaration of ‘operator+’ as non-function
problem2.cpp:282:45: error: expected ‘;’ at end of member declaration
problem2.cpp:282:47: error: expected unqualified-id before ‘<’ token

按照Raxvan的建議,我更改了代碼

模板類多項式;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

template <typename T>
ostream& operator <<(ostream& out, const Polynomial<T>& other);

....

template <typename T>
class Polynomial {
    ....

    public:

    ....

    friend ostream& operator << <> (ostream& out, const Polynomial<T>& other);

    Polynomial operator +(const Polynomial& other) const {
       // impelementation
    }

    template <typename NOT_T>
    friend const Polynomial<NOT_T> operator +(const Polynomial<NOT_T>& poly, const NOT_T& scalar);

};

template <typename T>
ostream& operator <<(ostream& out, const Polynomial<T>& other) {
    // implementation
}

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
    // implementation
}

在這段代碼中,運算符<<不會像運算符+那樣出現問題。 誰能解釋這個差異?

問題很細微。 您的語法非常接近正確。 我認為您的朋友聲明應該是:

friend Polynominal<T> const operator+<T>( ... );

但是VC ++和g ++都接受:

friend Polynominal<> const operator+<T>( ... );

當他們看到聲明時:

template <typename T>
const Polynomial<T> operator+(const Polynomial<T>& poly, const T& scalar);

(我無法在標准中找到任何可以證明這一點的理由,但是由於VC ++和g ++都可以做到這一點,所以我想這是我錯過的東西。)

問題就在這里。 類內定義隱藏了operator+命名空間范圍內的聲明。 編譯器抱怨是因為它發現的operator+ (類定義中)本身不是模板(盡管它是類模板的成員)。

如果您沒有operator<<的問題,那是因為您沒有同名的成員函數。

有幾種解決此問題的方法。 最簡單的方法可能是結交所有operator+朋友。 是否:最常見的方法是根據operator+=來實現operator+ (在所有情況下都應該是成員)。 在這種情況下, operator+不必是朋友。 或者您根本不將operator+作為模板,而是在類模板中將其定義為:

template <typename T>
class Polynomial
{
    friend Polynomial operator+( Polynomial const& lhs, Polynomial const& rhs )
    {
        //  ...
    }
    friend Polynomial operator+( Polynomial const& lhs, T const& rhs )
    {
        //  ...
    }
    friend Polynomial operator+( T const& lhs, Polynomial const& rhs )
    {
        //  ...
    }
}

(請注意,所定義的函數不是模板,而是單獨的重載非模板函數,每個實例化Polynomial 。但是結果最終是相同的。)

在這種情況下,您可能希望有一個由operator+函數調用的成員函數,該函數可以完成實際的工作; 您不需要像這樣直接內聯太多代碼。

將函數標記為好友時,必須具有相同的定義,這包括上面使用的具有另一種類型的模板,而不是T

template <typename T> class Polynomial;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

template <typename T>
class Polynomial {
public:

    template < class NOT_T> //must respect the deffinition from above
    friend const Polynomial<NOT_T> operator + (const Polynomial<NOT_T>& poly, const NOT_T& scalar);

};

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar)
{
    //...
}

編輯:

為了簡化說明,我將函數更改為foobar以說明聲明的區別:

template <typename T> class Polynomial;

template <typename T>
void bar(const Polynomial<T>& );

void foo(const Polynomial<float> & );//foo for speciffic float

template <typename T>
class Polynomial {
public:
    template <typename> //this is also valid declaration; 
    friend void bar(const Polynomial<T> & );
    //it just has to have template because it's a template functions declaration

    //not a valid declaration:
    //friend void bar <> (const Polynomial<T> & );

    //this declaration has no template;
    //it refers to a foo function specific to Polynomial<T> type
    //so if you use Polynomial<float> there must be a foo for floats
    friend void foo(const Polynomial<T> &);
};

template <class T>
void bar(const Polynomial<T>&)
{
}

void foo(const Polynomial<float> &)
{
}

void main()
{
    Polynomial<float>   pf;
    Polynomial<int>     pi;

    foo(pi);//error since there is not **foo** declared for int 
    foo(pf);//ok; we have **foo** for  Polynomial<float>

    bar(pf);
    bar(pi);//both ok since bar is templated function;
}

Raxvan。

您的operator+是一個功能模板,要使其成為朋友,您需要完整地聲明它,包括模板參數,但是使用不同的模板參數,例如:

#include <iostream>

template <typename T> class Polynomial;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

template <typename T>
class Polynomial {
    public:

    Polynomial operator +(const Polynomial& other) const {
      std::cout << "inline +" << std::endl;
    }

    // Here introduce a different type to indicate that this is a template...
    template <typename U>
    friend const Polynomial<U> operator + (const Polynomial<U>& poly, const U& scalar);

};

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
    std::cout << "friend +" << std::endl;
}

int main(void)
{
  Polynomial<int> f;

  f = f + 1;

  f = f + 1.; // this fails

  f = f + Polynomial<int>();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM