回答編集履歴

3

更に追記

2017/01/26 12:36

投稿

Chironian
Chironian

スコア23272

test CHANGED
@@ -127,3 +127,17 @@
127
127
  shared_ptrを使えば、デストラクト時の細かいタイミングを考慮する必要を回避できます。
128
128
 
129
129
  なお、Dataクラス内でAクラスをアクセスしたくなった時に、同じようにshard_ptrを使ってクラスAのインスタンスへのポインタをDataクラスで保持すると循環参照します。shard_ptrに頼って依存関係の設計に手を抜かなければ、大丈夫と思いますが。
130
+
131
+
132
+
133
+ ---
134
+
135
+ 【更に追記】
136
+
137
+ あっとと、シングルトンを使える状況(クラスAのインスタンスは1つしかない)であれば、単純に_dataをstaticメンバにすれば簡単です。別にシングルトン化する必要は特にありません。
138
+
139
+ みんな、A::_dataでアクセスできるようになります。
140
+
141
+ スケスケすぎて怖い場合は、_dataをprivateにしてBとCをAのfriendにすればOKです。
142
+
143
+

2

追記

2017/01/26 12:35

投稿

Chironian
Chironian

スコア23272

test CHANGED
@@ -99,3 +99,31 @@
99
99
  addData()関数ではなく、Dataクラスのデフォルト・コンストラクタでaddData()関数と同じ初期化をできると好ましいです。
100
100
 
101
101
  もし、パラメータを渡す必要がある場合は、それなりに工夫する必要があります。
102
+
103
+
104
+
105
+ ---
106
+
107
+ 【追加の質問への回答】
108
+
109
+ 依存関係をきっちり設計することは何れにせよ必須ですね。そして、きちんと設計されてますのできっちりプログラムすることが可能です。ですので、私なら参照を選択します。
110
+
111
+
112
+
113
+ ただ、もう少し知識が必要です。例えば、_objectBのデストラクタで_dataをアクセスするのであればその時まで_dataが生きている必要が有ります。_dataを_ojectBより先に定義するだけでそれを実現できますが、そのことを知っている人は少ないと思います。
114
+
115
+
116
+
117
+ [C++11の文法と機能](http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml)の[12.4 デストラクター(Destructors)](http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#class.conv.fct)より。
118
+
119
+ > デストラクターの呼び出しは、コンストラクター呼び出しの逆順に行われる。コンストラクター呼び出しの順番については、[12.6.2 基本クラスとデータメンバーの初期化](http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#class.base.init)を参照。
120
+
121
+ > 非staticデータメンバーの初期化の順番は、クラス定義の中でメンバーが宣言されている順番である。
122
+
123
+
124
+
125
+ そこで、深い知識を必要としないようなプログラミングをするのも1つの方針と思います。
126
+
127
+ shared_ptrを使えば、デストラクト時の細かいタイミングを考慮する必要を回避できます。
128
+
129
+ なお、Dataクラス内でAクラスをアクセスしたくなった時に、同じようにshard_ptrを使ってクラスAのインスタンスへのポインタをDataクラスで保持すると循環参照します。shard_ptrに頼って依存関係の設計に手を抜かなければ、大丈夫と思いますが。

1

追記

2017/01/26 12:29

投稿

Chironian
Chironian

スコア23272

test CHANGED
@@ -11,3 +11,91 @@
11
11
  ポインタはnullptrにできますし、ポイント先を変更できます。
12
12
 
13
13
  これらの操作が不要な時は参照を使うことでバグを避けやすくなります。
14
+
15
+
16
+
17
+ ---
18
+
19
+ 【追記】
20
+
21
+ ああ、でもよく見ると参照渡ししてますが、受け取り側はコピーで受け取ってますね。
22
+
23
+ それは勿体無いです。
24
+
25
+
26
+
27
+ ```C++
28
+
29
+ class C
30
+
31
+ {
32
+
33
+ public:
34
+
35
+ Data& _data;
36
+
37
+
38
+
39
+ C(Data& iData) : _data(iData)
40
+
41
+ { }
42
+
43
+ };
44
+
45
+
46
+
47
+ class B
48
+
49
+ {
50
+
51
+ public:
52
+
53
+ Data& _data;
54
+
55
+ C _objectC;
56
+
57
+
58
+
59
+ B(Data& iData) : _data(iData), _objectC(_data)
60
+
61
+ { }
62
+
63
+ };
64
+
65
+
66
+
67
+ class A
68
+
69
+ {
70
+
71
+ public:
72
+
73
+ Data _data;
74
+
75
+ B _objectB;
76
+
77
+
78
+
79
+ A() : _objectB(_data)
80
+
81
+ {
82
+
83
+ _data.addData(/*データを色々セット*/);
84
+
85
+ }
86
+
87
+ };
88
+
89
+ ```
90
+
91
+
92
+
93
+ 参照はコンストラクト時にのみ設定できますので、初期化子を使って初期化する必要があります。
94
+
95
+
96
+
97
+ そして、上記の初期化の場合、B, Cのオブジェクトがコンストラクトされる時はまだ_dataはデフォルト・コンストラクタでのみ初期化されおり、addData()は呼ばれていません。
98
+
99
+ addData()関数ではなく、Dataクラスのデフォルト・コンストラクタでaddData()関数と同じ初期化をできると好ましいです。
100
+
101
+ もし、パラメータを渡す必要がある場合は、それなりに工夫する必要があります。