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() может быть вызван.

Другие вопросы по тегам