web-dev-qa-db-ja.com

演算子<<は、1つの引数を取る必要があります

ああ

#include "logic.h"
...

class A
{
friend ostream& operator<<(ostream&, A&);
...
};

logic.cpp

#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...

私がコンパイルすると、それは言います:

std :: ostream&logic :: operator <<(std :: ostream&、A&) 'は引数を1つだけとる必要があります。

何が問題ですか?

79
As As

問題は、クラス内で定義することです。

a)2番目の引数が暗黙的(this)であり、

b)望んでいること、つまりstd::ostreamを拡張しません。

自由関数として定義する必要があります:

class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);
110
Cat Plus Plus

フレンド関数はメンバー関数ではないため、問題はoperator<<Aのフレンドとして宣言することです。

 friend ostream& operator<<(ostream&, A&);

それをクラスlogicのメンバー関数として定義してみてください

 ostream& logic::operator<<(ostream& os, A& a)
          ^^^^^^^

logicがクラスなのか名前空間なのか混乱していますか?

エラーは、2つの引数をとるメンバーoperator<<を定義しようとしたためです。つまり、暗黙のthisパラメーターを含む3つの引数が必要です。演算子は2つの引数のみを取ることができるため、a << bを記述すると、2つの引数はabになります。

ostream& operator<<(ostream&, const A&)non-member関数として定義します。logicのメンバーとしてではなく、そのクラスとは関係がないためです!

std::ostream& operator<<(std::ostream& os, const A& a)
{
  return os << a.number;
}
46
Jonathan Wakely

テンプレート化されたクラスでこの問題に遭遇しました。私が使用しなければならなかったより一般的なソリューションは次のとおりです。

template class <T>
class myClass
{
    int myField;

    // Helper function accessing my fields
    void toString(std::ostream&) const;

    // Friend means operator<< can use private variables
    // It needs to be declared as a template, but T is taken
    template <class U>
    friend std::ostream& operator<<(std::ostream&, const myClass<U> &);
}

// Operator is a non-member and global, so it's not myClass<U>::operator<<()
// Because of how C++ implements templates the function must be
// fully declared in the header for the linker to resolve it :(
template <class U>
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj)
{
  obj.toString(os);
  return os;
}

現在:*私のtoString()関数は、cppに隠れようとする場合、インラインにできません。 *ヘッダーにいくつかのコードが残っています。それを取り除くことができませんでした。 *オペレーターはtoString()メソッドを呼び出しますが、インライン化されていません。

Operator <<の本体は、friend節またはクラス外で宣言できます。両方のオプションはいです。 :(

多分私は何かを誤解したり見落としたりしているかもしれませんが、演算子テンプレートを前方宣言するだけではgccにリンクしません。

これも機能します:

template class <T>
class myClass
{
    int myField;

    // Helper function accessing my fields
    void toString(std::ostream&) const;

    // For some reason this requires using T, and not U as above
    friend std::ostream& operator<<(std::ostream&, const myClass<T> &)
    {
        obj.toString(os);
        return os;
    }
}

Operator <<を実装するためにテンプレート化されていない親クラスを使用し、仮想toString()メソッドを使用する場合、ヘッダーの宣言を強制するテンプレートの問題も回避できると思います。

3
Dan Truong