2011-10-07 11 views
8

私は基本クラスといくつかの派生クラスを持っています。これらの派生クラスに対して "< <"演算子をオーバーロードしたいと思います。通常の演算子、つまり「+」では、仮想関数がトリックを行います。私は標準的な慣習であることを理解することは私のクラス内<<演算子と継承クラスのオーバーロード

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

を宣言し、クラスの後に関数を定義することです。先験的に、私は上記の定義に仮想を追加すると動作すると思うでしょうが、いくつかの考え(そして私のコンパイラからのエラー)の後、それはあまり意味がないことを理解しています。

すべてのクラスメンバーが公開されているテストケースで、さまざまなタックを試しました。例えば: - 基底クラスのオペレータ< <派生クラスの演算子ではなく、呼び出されている

class Foo{ 
//bla 
}; 

ostream& operator<<(ostream& out, Foo& foo){ 
    cout << "Foo" << endl; 
    return foo; 
} 

class Bar : public Foo{ 
//bla 
}; 

ostream& operator<<(ostream& out, Bar& bar){ 
    cout << "Bar" << endl; 
    return bar; 
} 

/////////////////////// 

Bar bar = Bar(); 
cout << bar << endl; // outputs 'Foo', not 'Bar' 

だから、いくつかの方法で、これは「悪いなくなっ多型」です。上の例では、派生クラスのために正しい演算子を呼び出す方法を教えてください。さらに一般的には、私のクラスにプライベートメンバーがいて保護したいのであれば、friendキーワードを使ってオペレータのオーバーロードを修正するにはどうしたらいいですか?

答えて

6

仮想ヘルパー機能を使用できます。ここでは完全にテストされていない例ですので、任意の文法ミスを言い訳:

virtual ostream& Foo::print(ostream& out) const { 
    return out << "Foo"; 
} 

virtual ostream& Bar::print(ostream& out) const { 
    return out << "Bar"; 
} 

// If print is public, this doesn't need to be a friend. 
ostream& operator<<(ostream& out, const Foo& foo) { 
    return foo.print(out); 
} 

編集:は@Omnifariousの提案ごとにクリーンアップ。

+0

完全に動作します。ありがとう。 – andyInCambridge

+0

これには2つの欠陥があると思います。 1つの欠陥は大きな欠陥であり、もう1つは小さな欠陥です。巨大な欠陥が最初に...あなたは目に見えないほどの 'endl'を置くべきではありません。 'endl'はストリームを強制的にフラッシュしますが、これは状況によっては大きなパフォーマンス上の問題となります。 ''\ n' 'を使います。実際、 'endl'は' \ n 'を出力するという意味で定義されており、オーバーヘッドが発生しません。次に、 'return out <<" Foo \ n ";"。少し洗練されています。概念的には、すべてのものを '<<'操作の長い連鎖に変えます。 – Omnifarious

+0

@Omnifarious 'endl'を' operator << 'オーバーロードに決して入れません。 OPのコード。 –

1

operator<<virtualクラスのメソッドFooに転送するフリー関数にします。

See it in action

+0

これはうまくいきます!ありがとう。 – andyInCambridge

2

通常、ただ1つのフリーフレンド機能によって呼び出される基本クラスに多態的なprintメソッドを作成します。

+0

印刷物が公開されている場合は、その友人を捨てることができます。 –

+0

良い点、すべての周り、ありがとう。 – andyInCambridge

1

適切なコード修正が行われていれば、コードは正常に動作します。を行うことには何もありません:

ostream& operator<<(ostream& out, Foo& foo) { 
    out << "Foo" << endl; // 'out' and not 'cout' 
    return out; // returns 'out' and not 'foo' 
} 

ostream& operator<<(ostream& out, Bar& bar) { 
    out << "Bar" << endl; // 'out' and not 'cout' 
    return out; // returns 'out' and not 'bar' 
} 

Demoprivateメンバーにアクセスするには、この機能をclassfriendにすることができます。

+1

興味深い。私の実際のコードでは、私は叫びの代わりに正しく使い切っていましたが、それでも動作しませんでした。フィラーによって捕らえられない微妙なものがなければならない。// blaクラス。 – andyInCambridge

関連する問題