我有一个顶级类,使用组合实例化子模块。用户知道顶级类将具有这些子模块。将子模块对象设为公共成员以便用户可以直接调用它们的函数是一个好主意吗?
替代方案似乎是包装它们的函数调用,以保护子模块不被公开,但是由于用户需要指定子模块,所以没有任何封装优势。
这是一个顶级的房子,有子模块厨房和浴室。
// Public member objects
class Kitchen {
public:
void turn_on_tap();
int compute_area();
};
class Bathroom {
public:
void turn_on_tap();
int compute_area();
};
class House {
public:
Kitchen kitchen;
Bathroom bathroom;
int compute_area() { return kitchen.compute_area() + bathroom.compute_area(); }
};
//User code:
House house;
house.kitchen.turn_on_tap();
house.bathroom.turn_on_tap();
house.compute_area() // OK
house.bathroom.compute_area(); // may not want user to be able to do this
// Private member objects
class House {
Kitchen kitchen;
Bathroom bathroom;
public:
void turn_on_kitchen_tap() { kitchen.turn_on_tap(); }
void turn_on_bathroom_tap() { bathroom.turn_on_tap(); }
int compute_area() { return kitchen.compute_area() + bathroom.compute_area(); }
};
//User code:
House house;
house.turn_on_kitchen_tap();
house.turn_on_bathroom_tap();
house.compute_area();
我更喜欢第一种语法,但这意味着将成员对象公之于众。
第二种方法似乎很乏味,因为我必须编写额外的函数来包装底层函数调用。我失去了漂亮的点分层解除引用,因为用户知道(并且需要知道)底层层次结构。
编辑:但如果我将它们公之于众,我将在厨房和浴室中公开其他后端公共功能,我不一定希望用户知道。那么我可能不得不将这些私有化并使用“朋友”,这有点难看。
在上面的代码中添加了compute_area()。
这取决于。如果房子是一个简单的集合,即:
House
的有效值是Kitchen
和Bathroom
的有效值的任意组合。也就是说,没有House
特定的不变量可以保留。然后是的,一个简单的struct
(默认的公共访问)确实是正确的。这里的“封装”只是一种冗长的练习。有时你需要的对象只是粘在一起的一堆东西,没有进一步的逻辑。
因此,无论是否一个好主意,您都需要自己检查自己的应用程序。