オブジェクトが所有していないb
オブジェクトを内部的に参照して使用する場合、の死は病気になる可能性があります。ポイントを説明するための最小限の例を次に示します。a
a
b
#include <iostream>
const int my_int = 5;
class A {
private:
int n_;
public:
int n() const { return n_; }
A(int);
};
A::A(int n__) : n_(n__) {}
class B {
private:
const A *ap_;
public:
int m() const { return 1 + ap_->n(); }
explicit B(const A *);
};
B::B(const A *const ap__) : ap_(ap__) {}
int main()
{
std::cout << "Will put an unnamed A on the heap.\n";
A *const p = new A(my_int);
std::cout << "Have put an unnamed A on the heap.\n";
std::cout << "p->n() == " << p->n() << "\n";
B b(p);
std::cout << "b. m() == " << b. m() << "\n";
std::cout << "Will delete the unnamed A from the heap.\n";
delete p;
std::cout << "Have deleted the unnamed A from the heap.\n";
std::cout << "b. m() == " << b. m() << "\n"; // error
return 0;
}
もちろん、ポインタではなくb
のコピーを保持することでこれを修正できますが、コピーを保持しない方がよいと仮定します(大量のメモリを占有するなどの理由で)。単に既存のを参照することを好むと仮定します。静かに死ぬとき、決して気づかない。次に、を使用しようとすると、予測できない動作が発生します。a
b
a
b
a
a
b
b
a
私のコンピューターでは、例の出力は次のようになります。
Will put an unnamed A on the heap.
Have put an unnamed A on the heap.
p->n() == 5
b. m() == 6
Will delete the unnamed A from the heap.
Have deleted the unnamed A from the heap.
b. m() == 1
ただし、コンピュータでは、結果はセグメンテーション違反または誰が何を知っているかである可能性があります。
私の例の問題は、例が間接的にのカプセル化を破り、の継続的な有効性がの継続的な存在に依存するb
ことを覚えておくようにプログラマーに任せていることにあるようです。プログラマーが忘れると、プログラムは壊れます。したがって、嫌がらせを受けたプログラマーは、タイプA自体がタイプBを気にしない場合でも、作業するときは常に覚えておく必要があります。ご存知のように、オブジェクト指向プログラマーは、彼らがそれを助けることができるならば、そのような雑学を心に留める必要がないことを好みます。b
a
b
a
私はプログラミング中に時々より複雑な装いでこの問題に遭遇します。今日も会いました。どういうわけか、の適切なカプセル化を維持しb
、プログラマーからコンパイラーに「存在b
への依存」を記憶する責任を移すためのエレガントなデザインパターンが存在する必要がa
あり、パターンは基本的に何かより少ないものを含む必要があると感じますスマートポインタや本格的な参照カウントよりも複雑です。しかし、多分私は間違っています。たぶん、これはまさにそれらの参照カウントのスマートポインタの目的です。いずれにせよ、私は問題に対して適用する正しいパターンも、コードを修正するための最良の方法も知りません。
あなたが知っているなら、あなたはそれについて教えてくれますか?
これは、 Stackoverflowですでに気付いた最も関連性の高い回答です。しかし、私が理解していない1つか2つの単語を使用する以外に、その答えはとにかくこの質問に答えていないようです。
(私のコンパイラはまだC ++ 11をうまくサポートしていませんが、C ++ 11が私の問題に対処することを特に意図した機能をもたらす場合は、もちろんそれについて学ぶことに興味があるはずです。しかし、確かに、私の質問は主にOO /スコーピングの基本に関係します。質問は、これや最新のコンパイラの新機能よりも、基礎となるデザインパターンにさらに関心があります。)
読者への注意
いくつかの良い答えがこの質問を飾っています。Stackoverflowでは、ご存知のように、(今月または数年後に読んだときに)ベストアンサーを検索する必要がないように、質問者はベストアンサーを受け入れる責任があります。
ただし、この質問に最もよく答えるのは2つの答えの組み合わせです。あなたは両方を読むべきです: