Pregunta

Dado el siguiente código de ejemplo:

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(); }
}

Entiendo aquí es que el segundo TurnOn() implica un nivel adicional de indirección, ya que debemos seguir la referencia a la habitación. ¿Es esto correcto? ¿Se eliminará esa indirección adicional si la llamada se puede ingresar (ya sea a través de la incrustación explícita o la optimización completa del programa a nivel de enlazador)? O, puesto de manera diferente, ¿podría acelerar la función de Turnon en Switch cambiándola a:

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(); }
}

O, más generalmente, si tiene una referencia a un objeto, ¿hay un nivel de indirección menos involucrado en acceder a sus miembros directamente a través de una referencia en lugar de a través de la referencia y luego el miembro?

Gracias

¿Fue útil?

Solución

Eso puede que ser más rápido (aunque no por mucho). Sin embargo, ambos ejemplos son incorrectos en el sentido de que rompen la encapsulación y violan el Ley de Deméter. Requieren que o el Switch clase o cualquier persona que lo instancie tiene acceso a ambos Room en sí y el Lamp dentro de eso. Por supuesto, también estamos asumiendo que cada habitación tiene una lámpara, y que una lámpara solo puede existir dentro de una habitación ... lo que significa que si esas condiciones cambian, hay dos clases para cambiar en lugar de solo una.

El primer ejemplo estaría mejor escrito como

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;
};

como entonces el Room es responsable de lo que se enciende. Podría ser una lámpara, podría ser una radio. Switch Ya no tiene que importarle. Es más probable que sea más lento, pero es más mantenible.

Si quieres requerir eso Switch solo enciende un Lamp, después

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;
};

Esto debería ser igual de rápido, sin requerir que rompamos la encapsulación.

Otros consejos

Su segundo ejemplo (probablemente) no será más rápido que el primer ejemplo. En ambos casos, una referencia debe resolverse antes TurnOn() se puede invocar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top