別のメンバーからメンバーにアクセスする際のC ++間接
-
28-10-2019 - |
質問
次の例を与えられたコード:
class Room {
Room() : switch(*this) { }
Lamp lamp;
Switch switch;
void TurnOn() { lamp.TurnOn(); }
}
class Switch {
Switch(Room& room) : room(room) { }
Room& room;
void TurnOn() { room.lamp.TurnOn(); }
}
ここでの私の理解は、2番目のことです TurnOn()
部屋への参照に従う必要があるため、追加のレベルの間接が含まれます。これは正しいです?呼び出しが挿入された場合(明示的なインライン化、またはリンカーレベルでのプログラム全体の最適化のいずれかを介して)場合、その余分な間接は削除されますか?または、別の言い方をすれば、スイッチのターンロン関数を次のように変更することでスピードアップできます。
class Room {
Lamp lamp;
Switch switch;
Room() : switch(*this,lamp) { }
void TurnOn() { lamp.TurnOn(); }
}
class Switch {
Room& room;
Lamp& lamp;
Switch(Room& room,Lamp& lamp) : room(room),lamp(lamp) { }
void TurnOn() { lamp.TurnOn(); }
}
または、より一般的には、オブジェクトへの参照を保持する場合、参照を介してメンバーを介して参照を介して直接メンバーへのアクセスにあまり関与していないレベルの間接がありますか?
ありがとう
解決
これ そうかもしれない より速くなります(それほどではありませんが)。ただし、両方の例は、カプセル化を破って違反するという点で間違っています。 デメテルの法則. 。どちらかが必要です Switch
クラスまたはそれをインスタンス化する人は両方にアクセスできます Room
それ自体と Lamp
その中。もちろん、すべての部屋にランプがあり、ランプが部屋内にしか存在しないと仮定しています...つまり、それらの条件が変化した場合、1つだけでなく変更する2つのクラスがあります。
最初の例は、としてよりよく書かれています
class Room {
public:
Room() : sw(*this) { }
void TurnOn() { lamp.TurnOn(); }
private:
Lamp lamp;
Switch sw;
};
class Switch {
public:
Switch(Room& room) : room(room) { }
void TurnOn() { room.TurnOn(); }
private:
Room& room;
};
そのように Room
オンになっているものに責任があります。ランプである可能性があり、ラジオである可能性があります。 Switch
もう気にする必要はありません。これは遅くなる可能性が高くなりますが、より保守可能です。
あなたがそれを要求したい場合 Switch
オンのみをオンにします Lamp
, 、 それから
class Room {
public:
Room() : sw(lamp) { }
void TurnOn() { lamp.TurnOn(); } // (semantics: who "turns on" a room?)
private:
Lamp lamp;
Switch sw;
};
class Switch {
public:
Switch(Lamp& lamp) : lamp(lamp) { }
void TurnOn() { lamp.TurnOn(); }
private:
Lamp& lamp;
};
これは、カプセルを破ることを要求することなく、同じくらい速くなければなりません。
他のヒント
2番目の例は(おそらく)最初の例よりも速くないでしょう。どちらの場合も、1つの参照を以前に解決する必要があります TurnOn()
呼び出すことができます。