条款36:绝不重新定义继承而来的non-virtual函数

2024-01-08 16:12

本文主要是介绍条款36:绝不重新定义继承而来的non-virtual函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.前言

假设class D是由class B以public形式派生而来,class B定义有一个public成员函数mf,由于mf的参数和返回值都不重要,所以定义两者都为void。即:

class B{public:void mf();...
};class D:public B{...};

2.实例分析

在这里,虽然我们对B和D及mf都一无所知,但面对一个类型为D的对象x:、

D x;//x是一个类型为D的对象

如果以下行为:

B* pB=&x;//获得一个指针指向x
pB->mf();//经由该指针调用mf
不同以下行为:
D* pD=&x;//获得一个指针指向x
pD->mf();//经由该指针调用mf

为什么两种用法会不同呢,毕竟都是通过对象x调用成员函数mf。由于两者所调用的函数都相同,凭借的对象也相同。

但实际上是这样的,更明确地说:如果mf是个non_virtual函数而D定义有自己地mf版本,那就不是如此:

class D:public B{public:void mf();//遮掩了B::mf()...
};
pB->mf();//调用B::mf
pD->mf();//调用D::mf

造成产生这种现象地原因是non-virtual函数如B::mf和D::mf都是静态绑定。这表明pB被声明为一个pointer-to-B,通过pB调用地non-virtual函数永远是B所定义地版本,即使pB指向一个类型为“B派生之class”地对象

另一方面,virtual函数却是动态绑定,所以它们不受该问题地困扰。如果mf是个virtual函数,不论是通过pB或者pD调用mf,都会导致调用D::mf,因为pB和pD真正指向地是一个类型为D地对象

如果你正在编写class D并重新定义继承自class B地non-virtual函数mf,D对象很可能产生相互矛盾地不一致行为。更明确地说当mf被调用时,任何一个D对象都可能表现出B或者D地行为:决定因素不在对象自身,而在于指向该对象地指针当初声明地类型。reference也会展现和指针一样难以理解地行径。

现在如果重新定义mf,设计便会出现矛盾,如果D真有必要实现出与B不同地mf,并且每一个B对象真的必须使用B所提供地mf实现码,那么每个D都是一个B就不为真。既然如此D就不该以public形式继承B。另一方面,如果D真地必须以public方式继承B,并且如果真有需要实现出与B不同地mf,那么mf就无法为B反映出“不变性凌驾于特异性”的性质。既然这样mf应该声明为virtual函数。最后如果每个D真的是一个B,并且如果mf真的为B反映出“不变性凌驾于特异性”的性质上,那么D便不需要重新定义mf,而且它也不应该尝试这样做。

不论哪一个观点,结论都一样:任何情况下都不该重新定义一个继承而来的non-virtua函数。

这篇关于条款36:绝不重新定义继承而来的non-virtual函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/584026

相关文章

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

Java 继承和多态的作用及好处

《Java继承和多态的作用及好处》文章讲解Java继承与多态的概念、语法及应用,继承通过extends复用父类成员,减少冗余;多态实现方法重写与向上转型,提升灵活性与代码复用性,动态绑定降低圈复杂度... 目录1. 继承1.1 什么是继承1.2 继承的作用和好处1.3 继承的语法1.4 子类访问父类里面的成

python 常见数学公式函数使用详解(最新推荐)

《python常见数学公式函数使用详解(最新推荐)》文章介绍了Python的数学计算工具,涵盖内置函数、math/cmath标准库及numpy/scipy/sympy第三方库,支持从基础算术到复杂数... 目录python 数学公式与函数大全1. 基本数学运算1.1 算术运算1.2 分数与小数2. 数学函数