12

C++ の getter と setter の適切な構文を知りたいです。

private:
YourClass *pMember;

セッターは簡単だと思います:

void Member(YourClass *value){
  this->pMember = value; // forget about deleting etc
}

そしてゲッター?参照または const ポインターを使用する必要がありますか?

例:

YourClass &Member(){
   return *this->pMember;
}

また

YourClass *Member() const{
  return this->member;
}

それらの違いは何ですか?

ありがとう、

ジョー

編集:

申し訳ありませんが、質問を編集します...参照とポインターについて知っています。参照とconstポインターについてゲッターとして尋ねていました。コード内でそれらの違いは何ですか。どっちに転んでも負ける…

したがって、参照の代わりに const ポインターを使用すると思います

const ポインターは削除または設定できませんよね?

4

8 に答える 8

17

一般的な法律として:

  • NULL が有効なパラメーターまたは戻り値である場合は、ポインターを使用します。
  • NULL が有効なパラメータまたは戻り値でない場合は、参照を使用してください。

セッターが NULL で呼び出される可能性がある場合は、ポインターをパラメーターとして使用します。それ以外の場合は、参照を使用してください。

NULL ポインターを含むオブジェクトの getter を呼び出すことが有効な場合は、ポインターを返す必要があります。そのような場合が不正な不変条件である場合、戻り値は参照になるはずです。メンバー変数が NULL の場合、getter は例外をスローする必要があります。

于 2009-10-20T18:25:07.380 に答える
7

あなたのコードは、あたかも別の言語に慣れているかのように見えます.C++では、this->x(一例として)使用することは比較的まれです. コードが適切に作成されている場合は、アクセサーまたはミューテーターを使用しています。

私はこの特定の点でかなり変わっていますが、クライアントコードにアクセサーまたはミューテーターを直接使用させることは悪い考えであると言っているので、(もう一度)記録に残します。正直なところ、クライアント コードでオブジェクトの値を操作することが理にかなっている場合、クライアント コードは通常の代入を使用してその値を読み書きする必要があります。

どの値が割り当てられるかを制御する必要がある場合は、演算子のオーバーロードを使用すると、クライアント コードで醜い get/set 構文を強制することなく、その制御を行うことができます。具体的には、プロキシ クラス (またはクラス テンプレート) が必要です。ほんの一例として、get/set 関数が必要になる最も一般的な状況の 1 つは、特定の範囲に制限されるはずの数値のようなものです。はsetXXX新しい値が範囲内にあるかどうかをチェックし、 はgetXXX値を返します。

あなたがそれを望むなら、(かなり)単純なテンプレートは仕事をもっときれいに行うことができます:

template <class T, class less=std::less<T> >
class bounded {
    const T lower_, upper_;
    T val_;

    bool check(T const &value) {
        return less()(value, lower_) || less()(upper_, value);
    }

    void assign(T const &value) {
        if (check(value))
            throw std::domain_error("Out of Range");
        val_ = value;
    }

public:
    bounded(T const &lower, T const &upper) 
        : lower_(lower), upper_(upper) {}

    bounded(bounded const &init) 
        : lower_(init.lower), upper_(init.upper)
    { 
        assign(init); 
    }

    bounded &operator=(T const &v) { assign(v);  return *this; }

    operator T() const { return val_; }

    friend std::istream &operator>>(std::istream &is, bounded &b) {
        T temp;
        is >> temp;

        if (b.check(temp))
            is.setstate(std::ios::failbit);
        else
            b.val_ = temp;
        return is;
    }
};

これにより、コードが自己文書化にかなり近づきます。たとえば、次のようなオブジェクトを宣言するbounded<int>(1, 1024);と、その意図が 1 から 1024 の範囲の整数であることがすぐにわかります 1 および/または 1024 が範囲に含まれるかどうか。これは、クラスで int を定義することとはかなり異なります。また、クラスを見たすべての人が、setXXX を使用して (その時点では未知の) 値の境界のセットを適用する必要があることを理解することを期待しています。割り当てられます。

これらのいずれかをクラスに埋め込む場合、それをパブリック変数にすると、範囲は引き続き適用されます。クライアント コードには、構文に関する実際の引数はありません。他の場合と同様に、パブリック変数に代入するだけです。範囲外の値を代入しようとすると例外がスローされるという細かい点があります。理論的には、クラスはおそらくポリシー テンプレート パラメータを使用して、その場合に何を行うかを正確に指定する必要がありますが、それを気にする本当の理由はありませんでした。

于 2009-10-20T19:40:01.840 に答える
7

最良の方法は、実装の詳細を隠す実際の OO インターフェイスをクライアントに提供することです。ゲッターとセッターはオブジェクト指向ではありません。

于 2009-10-20T18:32:41.123 に答える
4

他の人が言ったように、null の可能性がある場合はポインターを使用してください。

ほとんどの場合、可能であれば参照を使用することを好みます。個人的には、私のコードでは、所有権を示すためにポインターと参照の違いを使用するのが好きです。参照を伴う呼び出しは、オブジェクトを別の関数またはクラスに「貸与」するものと考えています。参照を渡したり返したりした元のクラスは引き続きそれを所有し、その作成、保守、およびクリーンアップを担当します。一方、私のコードが非 const ポインターを渡す場合、通常は、所有権の譲渡または共有が行われ、それに伴うすべての責任が発生することを意味します。

(そして、はい、私は通常、スマート ポインターを使用します。それらは、私の頭の中では参照に似ています。ここでは、それよりも低レベルのコードについて話しているのです。)

于 2009-10-20T18:37:58.250 に答える
2

それらの違いは何ですか?

参照はモノの別名です (それモノです*)。ポインタはモノのアドレスです。指し示されているものがそこにない可能性がある場合は、おそらく参照を返したくないでしょう。参照は、発信者に「返信したときに存在するエイリアスを提供します」と伝えます。実際、参照をチェックして、基になっているものが有効かどうかを確認する方法はありません。

ポインターを使用すると、意味的には、呼び出し元が Member を使用する前に存在するかどうかを確認する必要があることを暗示しています。通常、これは NULL チェックで行われます。

結局、「正解」はありません。クラスの契約と、呼び出し元が「メンバー」がまだ存在するかどうかを確認する/する必要がある/確認するかどうかによって異なります。

簡単な答えは、他の場所で指し示すことができるものへのポインターと、「着席していない」エイリアスへの参照です。

于 2009-10-20T18:25:44.947 に答える
2

他の回答に加えて、ゲッターの参照を選択する場合は、例のように記述しないでください。

YourClass &Member(){
   return *this->pMember;
}

ゲッターは実際に設定を許可するinstance->Member() = YourClass();ため、セッターをバイパスします。YourClass がコピー不可能な場合、これは許可されない可能性がありますが、それでも心に留めておくべきもう 1 つのことです。もう 1 つの欠点は、ゲッターが const ではないことです。

代わりに、次のようにゲッターを記述します。

const YourClass &Member() const {
   return *this->pMember;
}
于 2009-10-20T20:08:38.950 に答える
1

セッターとゲッターの使用に関する質問に+1。それらを使用する必要があり、null の可能性がある場合は、boost::shared_ptr の使用を検討してください。このようにして、所有権が処理されます。

于 2009-10-20T18:37:31.450 に答える
0

ジョナサン、あなたはどのコンパイラを使用していますか? shared_ptrコンパイラの TR1 実装の一部として、すでに同梱されている可能性が非常に高いです。

于 2009-10-20T19:26:21.920 に答える