C++ Непрямость при доступе к членам от другого участника
Учитывая следующий пример кода:
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(); }
}
Я понимаю, что второе TurnOn()
предполагает дополнительный уровень косвенности, так как нам нужно следовать ссылке на комнату. Это правильно? Будет ли устранена эта дополнительная косвенность, если вызов может быть встроен (либо посредством явного встраивания, либо путем оптимизации всей программы на уровне компоновщика)? Или, другими словами, можно было бы ускорить функцию TurnOn в Switch, изменив ее на:
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(); }
}
Или, в более общем смысле, если имеется ссылка на объект, существует ли уровень косвенности, который в меньшей степени связан с доступом к его элементам напрямую через ссылку, а не через ссылку, а затем элемент?
Спасибо
2 ответа
Это может быть быстрее (хотя и ненамного). Однако оба примера неверны в том смысле, что они нарушают инкапсуляцию и нарушают закон Деметры. Они требуют, чтобы либо Switch
класс или любой, кто его создает, имеет доступ к обоим Room
сам и Lamp
внутри него. Конечно, мы также предполагаем, что в каждой комнате есть Лампа, и что Лампа может существовать только в пределах комнаты... что означает, что если эти условия когда-либо изменятся, то нужно изменить два класса вместо одного.
Первый пример лучше записать как
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;
};
Это должно быть так же быстро, без необходимости ломать инкапсуляцию.
Ваш второй пример (вероятно) будет не быстрее первого. В обоих случаях одна ссылка должна быть разрешена до TurnOn()
может быть вызван.