C ++ Непрямость при доступе к элементам от другого участника - PullRequest
0 голосов
/ 05 декабря 2011

С учетом следующего примера кода:

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 ]

1 голос
/ 05 декабря 2011

Это может быть быстрее (хотя и ненамного).Однако оба примера неверны в том смысле, что они нарушают инкапсуляцию и нарушают закон Деметры .Они требуют, чтобы либо класс 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;
};

Это должно быть простотак быстро, не требуя, чтобы мы нарушили инкапсуляцию.

0 голосов
/ 05 декабря 2011

Ваш второй пример (вероятно) будет не быстрее первого. В обоих случаях необходимо разрешить одну ссылку, прежде чем можно будет вызвать TurnOn().

...