C++编程规范之37:公用继承即可替换性。继承,不是为了重用,而是为了被重用

简介:

摘要:

    知其然:公用继承能够使基类的指针或者实际引用指向某个派生类的对象,既不会破坏代码的正确性,也不需要改变已有的代码。

    还要知其所以然:不要通过公用继承重用(基类中的已有)代码,公用继承是为了被(已经多态地使用了基对象的已有代码)重用的。

    按照Liskov替换原则(LiskovSubstitution Principle),公用继承所建模的必须总是“是一个(is-a)”关系:所有基类约定必须满足这一点,因此如果依靠成功地满足基类的约定,所有虚拟成员函数的改写版本就必须不多于其基类版本,其承诺的也必须不少于其基类版本。使用指向Base的指针或者引用的代码必须能正确工作,即使指针或者应用实际上指向的是Derived。

    继承的误用将破坏正确性。没有被正确实现的继承大多数都会无法遵守基类确定的显式或者隐式约定而迷乱。这种约定可能是很微妙的,如果无法在代码中直接表达,程序员就必须格外小心。

    公用继承的目的是实现可替换性,公用继承的目的并不是为了派生类重用积累的代码,从而用基类代码实现自己。这种“用……来实现”的关系可能完全没有问题,但是应该用组合关系来建模——或者仅仅在某些特殊情况下,通过非公用继承来实现。

    还可以用另一种说法来表述:当动态多态正确而且适合时,组合是自私的,而继承是慷慨的。心的派生类是已有通用抽象的新特例。已有的动态代码通过调用Base的虚拟函数来使用Base&或者Base*,应该能够无缝地使用继承自Base的MyNewDerivedType的对象。心的派生类型向已有代码中添加新功能时,不需要修改已有代码,而是可以在加入新派生对象时无缝地增加其功能。

    新的需求应该很自然地由新代码满足,心的需求不应该导致对已有代码的重新改写。

在面向对象技术出现之前,新代码掉哟个已有代码就一直很容易。尤其是公用继承使已有代码安全无缝地调用新代码变得更加容易了。

相关文章
|
4天前
|
安全 前端开发 Java
【C++】从零开始认识继承二)
在我们日常的编程中,继承的应用场景有很多。它可以帮助我们节省大量的时间和精力,避免重复造轮子的尴尬。同时,它也让我们的代码更加模块化,易于维护和扩展。可以说,继承技术是C++的灵魂。
14 1
|
4天前
|
安全 程序员 编译器
【C++】从零开始认识继承(一)
在我们日常的编程中,继承的应用场景有很多。它可以帮助我们节省大量的时间和精力,避免重复造轮子的尴尬。同时,它也让我们的代码更加模块化,易于维护和扩展。可以说,继承技术是C++的灵魂。
24 3
【C++】从零开始认识继承(一)
|
4天前
|
存储 算法 测试技术
|
4天前
|
程序员 编译器 C++
|
4天前
|
存储 编译器 C++
C++中的继承
C++中的继承
11 0
|
4天前
|
设计模式 算法 编译器
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
13 0
|
4天前
|
安全 程序员 编译器
【C++】继承(定义、菱形继承、虚拟继承)
【C++】继承(定义、菱形继承、虚拟继承)
15 1
|
4天前
|
安全 编译器 程序员
[C++基础]-继承
[C++基础]-继承
|
4天前
|
设计模式 安全 算法
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
18 0
|
2天前
|
测试技术 C++
C++|运算符重载(3)|日期类的计算
C++|运算符重载(3)|日期类的计算