为接口和实现设置单独的命名空间是否值得?
Stroustrup在他的C ++书(第四版)中的建议是我们应该使用不同的命名空间 用于接口和实现。经验丰富的人可以说些什么 在这一个?我的意思是听起来不错,但是它真的很实用,它是否有意义 现实世界的项目?
答案 0 :(得分:5)
命名空间会告诉您该定义属于谁。当然,接口属于与实现不同的组是有意义的;这就是界面,关注点分离的重点。
答案 1 :(得分:2)
在实现繁重的代码中(比如Boost中的一些元编程怪物),一眼就能看出你希望能够直接使用哪些代码,以及你可以安全地忽略哪些代码是有用的。库detail
命名空间中的代码被视为“内部”代码,因此当您在堆栈跟踪中看到detail
符号时,无需花时间查阅文档。
我不会说它有一个巨大的好处,在一般情况下肯定不是这样,但是因为它没有造成任何伤害,所以你可以保持整洁和隔离。< / p>
答案 2 :(得分:0)
在现实世界的项目中有意义吗?
是的,例如在boost中它被广泛使用。以boost::shared_ptr
为例。一看到namespace detail
,我就立即知道我没有太深入研究该代码段,除非有一条错误消息告诉我这样做(即便如此,这很可能是我的错)。
我猜你知道怎么驾驶汽车。有许多接口:方向盘,燃气/断路器/离合器踏板,显示器等。你有兴趣使用这些接口,毕竟,这就是你使用汽车的方式:
namespace the_company{
struct wheel{
void turnLeft(deg);
void turnRight(deg) { turnLeft(-deg); }
};
struct pedal{
void tap();
void press_completely_till_something_happens();
//!< might deadlock if using break and car isn't moving
};
struct display{
so_many_colors lookat();
};
}
为了这个例子,我们将它们组合在一起作为汽车,但是将东西分成不同的命名空间不仅对OOP有用。
namespace the_company{
struct car{
public:
wheel & getWheel();
pedal & getBreakPedal();
...
};
}
我们对car
有什么期望?我们可以期待我们可以使用汽车的轮子或踏板,它将起作用:
car myCar;
myCar.getGasPedal().press_completely_till_something_happens();
// OH GOD; WHAT HAVE I DONE!?
myCar.getWheel().turnLeft(360);
myCar.getBreakPedal().press_completely_till_something_happens();
// Shew. That was close.
我们使用car
完全没问题。顺便说一句,我们没有将wheel
放入car
,因为我们公司可能会生产其他使用轮子的东西,例如船,卡车,人工飞机,阀门和其他非车辆物品,以及一个display
可能被更多不同的东西使用(手机,显示器,电视,你的名字)。
然而,为了实际运行汽车,它必须有一个引擎。由于引擎是一些相当复杂的机器,我们将它们隐藏在hood
:
namespace the_company{
namespace hood{
struct engine{
// heavily optimized code
// not so nice interface anymore
// maybe not even documentated
...
};
}
}
engine
是一只野兽,它具有可扩展性,适用于任何车辆或重型机械,贵公司在优化方面投入了大量精力。现在每当车主对他的引擎有问题时,他只需查看hood
并查看错误。
但它隐藏在某事物之后的事实已经从一开始就告诉用户他应该知道他将要做什么。如果他不理解金属/代码,他应该向他的服务维护/支持寻求帮助。
此外,engine
可能会改变甚至完全删除,因为我们公司发明了fusion_engine
,从而获得更好的利润。
这就是namespace detail
对我来说:错综复杂的细节,可能会改变,甚至可能只对原始维护者有意义。但那没关系。它不是界面的一部分。