当一个函数需要返回一个对象时。它应该通过指向 derived 还是 base 的指针返回它?
class B{
}
class D:public B{
}
// way 1: return pointer to derived
D* createDerived(){
D* d = new D();
return d;
}
// way 2: return pointer to base
B* createDerived(){
B* d = new D();
return d;
}
我听说过“面向接口(interface)而不是实现的程序”,它建议我们应该返回一个指向基的指针。然而我的直觉告诉我在这种情况下最好返回一个指向派生的指针,因为如果客户端代码使用基指针,这个函数仍然可以工作!另一方面,如果我们返回指向 base 的指针并且客户端代码使用派生指针,则这对它们不起作用。似乎通过返回一个更“具体”的指针,我们为客户端代码提供了更大的灵 active 。
另一种看待它的方式是从“program by contract”的角度来看。其中一项建议是尽可能少地 promise 。通过 promise 我们将返回一个非常具体的对象,我们遵循了这条规则。但是,如果我们返回一个基指针,在我看来,我们的希望更大。
哪个设计更好?我的上述推理是否正确?
关于如何制作模块化、可维护、可扩展的软件,我还有很多东西要学习,所以如果我的推理/结论不通俗易懂,请原谅。我对学习很感兴趣。非常感谢您抽出宝贵时间。
最佳答案
不可能笼统地回答这个问题。特别是,返回更多派生对象对该方法的 future 实现施加了额外的限制,而返回基类对调用者施加了更多限制。哪个最好取决于应用程序或库的设计,尤其是 B
和 D
提供的功能范围以及 API 的总体设计。
一般来说,您希望返回最派生的类,或者笼统地说,最实用的类,这不会限制您 future 的实现选择。这允许您的客户有效地使用返回值,同时仍然允许您在未来更改实现。
使用派生类 D
的主要缺点是您向客户端公开了更多细节,这可能很难或不可能在以后逆转。
例如,假设您有一个方法 reverse(std::ReversibleContainer &cont)
,它获取一个容器并返回它的反转快照(即,对底层容器的更改不会影响返回的快照)。
在您的初始实现中,您可能决定将其实现为:
template<class BidirectionalIterator>
std::list<T> reverse(BidirectionalIterator &start, BidirectionalIterator &end) {
std::vector output;
std::copy(input.begin(), input.end(), back_inserter(output))
return output;
}
稍后,您可能会意识到,在容器(和元素)不变的某些情况下,您可以避免底层数据的复制,例如:
ImmutableIterator reverse(ImmutableBiderectionalIterator &input) {
return ReversingImmutableBiderectionalIterator(input);
}
此容器可以使用输入容器是只读的知识来返回输入容器的 View ,避免复制,复制只是简单地重新映射每次访问以产生与反转容器。
关于c++ - 函数应该返回指向派生类还是基类的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35516558/