2010-12-13 7 views
11
class Temp { 
    public : 
     Temp(X& x): x_(x) {} 
     Temp(X& x, Y& y) : x_(x), y_(y) {} 
     ... 
    private: 
     X& x_; 
     Y& y_; 
} 

Temp(X& x): x_(x)の場合はy_が初期化されないため、エラーが発生しました。そのようなクラスを正しく書くための一般的な慣行は何ですか?メンバ参照を正しく初期化する

答えて

10

これはあなたが探しているものではないかもしれないが、別のアプローチを提案します。

参照変数(メモリポインタ)を使用せず、ブーストも使用しませんが、これ以上のメモリリソースを消費せずに両方のコンストラクタを保持することができます。参照であるデータメンバを持つ

#include <iostream> 

class Temp 
{ 
    public : 
     Temp(int& x): x_(&x), y_(NULL) {} 
     Temp(int& x, int& y) : x_(&x), y_(&y) {} 
     void print() { std::cout << "*x_: " << *x_ << std::endl; } 

    private: 
     int* x_; 
     int* y_; 
}; 

int main() 
{ 
    int x = 5; 
    Temp tmp(x); 

    tmp.print(); 

    return 0; 
} 
+1

既存の動作を維持するために' int * const x_; 'と' int * const y_; 'を考慮してください。再バインドされる)。 –

2

一般的なプラクティスは、すべての正直なところ、構造体またはクラスのデータメンバーとして参照を使用しないことです。

なぜあなたはこれをしたいと思いますか?概念は、概念的には、既存のものの別の名前です。オブジェクトは、まあ、オブジェクトです。あなたは布全体からそれらを作ることができなければなりません。時々彼らは既に存在する他のものへのポインタ(またはスマートポインタクラスのインスタンス)を持っていますが、少なくともポインタ自体は実データです。

+4

狭い視野で、私は同意しません。場合によっては、参照メンバが何かをキャプチャする最良の方法です。たとえば、一部のデータblobを解析または列挙するために使用される短命クラスは、そのデータblobへの参照を持つことがあります。 –

+2

-1:いいえ、クラスのメンバとしての参照は、参照されているオブジェクトの存在に関する制約です。既にそれを使用し、それが使用されて見た。 –

10

初期化されていない参照メンバを持つことはできません!このような場合は、boost::optionalに参照をラップすることを検討し、必要に応じて参照を作成することもできます。

編集:ここboost::optionalアプローチは、あなたがY_する参照を持っている...

class Temp { 
    public : 
     Temp(X& x): x_(x) {} 
     Temp(X& x, Y& y) : x_(x), y_(y) {} 
     ... 
    private: 
     X& x_; 
     boost::optional<Y&> y_; // by default this is constructed with none_t 
} 
+0

'boost :: optional'はテンプレート型の参照型で動作しますか?今私は彼らが働くようになった方法を調べたい –

+0

@Karl、yip - これは 'boost :: optional'の最大の特長です。IMHO ... – Nim

1

です!参照でなければなりません。最初のコンストラクタは初期化されていません。クラスの作成時にyにバインドできない場合は、おそらくポインタを使用するべきです。

0

最初のコンストラクタを削除するか、2番目の参照を削除します。参照がある場合は、すぐに初期化する必要があります。 Yメンバをデフォルトで初期化するコンストラクタを提供する必要がある場合は、Yメンバをポインタまたは自動変数にします。

7

STRONG契約です: それはあなたがnullptrまたは未定義のオブジェクトを持つことができないことを意味し、あなたのクラスは、このオブジェクトが必要、オブジェクトが存在する必要があります。

結果として、最初のコンストラクタがこの強力な契約に違反し、したがってコンパイルできません。

karlphillipは、_yが常に定義されていることを保証する契約を尊重したくないので、ポインタを使用することを推奨します。

あなたのクラスが参照されたオブジェクトの存在を前提としない感覚を持たない場合、それはメンバーとしての参照を持つことが有効です。

+0

確かに有効ですが、私の立場は、この種の「この他のものは存在しなければなりません」という前提が珍しく、**は設計上の瑕疵を示している可能性があります。この特定の機能のビットにOOを使用するなど)参照データのメンバーには扱いにくい場合があります.OPの問題に加えて、コピーコンストラクタまたは代入演算子を記述するタスクを検討してください。それは、適切なセマンティクスを推論するためにはるかに多くの思考が必要であり、コンパイラも満たすためにはもっと努力が必要です。しかし、契約を説明するために+1。 –

+0

@Karl、あなたの権利は時にはデザイン上の瑕疵かもしれません。私はあなたが与えた-1を取り除きます;-) –

+0

私は完全に柔軟性がないプログラミングの事はかなりあります。しかし、何かがしばしば正しいアイデアではないと思うとき、私は異議を強く言いたいのです。 "ああ、でも私は特別だ"。いいえ。特別なケースは十分ではありません。 ;) –

関連する問題