给出以下示例代码:
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()
涉及额外的间接层,因为我们需要遵循对空间的引用。它是否正确?如果可以内联调用(通过显式内联或链接器级别的整个程序优化),是否会删除额外的间接寻址?或者换句话说,Switch中的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(); }
}
或者,更一般地说,如果持有对象的引用,是否有一个间接级别参与直接通过引用而不是通过引用然后成员访问其成员?
由于
答案 0 :(得分:1)
可能更快(虽然不是很多)。但是,这两个示例都不正确,因为它们破坏了封装并违反了Law of Demeter。它们要求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;
};
这应该同样快,不要求我们打破封装。
答案 1 :(得分:0)
你的第二个例子(可能)并不比第一个例子快。在这两种情况下,都需要在调用TurnOn()
之前解析一个引用。