C++ 虚函数在基类与派生类对象间的表现及其分析

近来看了侯捷的《深入浅出MFC》,读到C++重要性质中的虚函数与多态那部分内容时,顿时有了疑惑。因为书中说了这么一句:使用“基类之指针”指向“派生类之对象”,由该指针只能调用基类所定义的函数,如果要让基类的指针使用派生类中定义的函数,就将该函数定义为虚函数

但在“Object slicing与虚函数”这一小节给出了一个及其经典的例子,它指出,在向上(即向基类)强制转型时,会造成对象内容的被切割

下面用示例进行说明:

 

#include "stdafx.h"
#include <iostream>
using namespace std;class A
{
public:virtual void fn(){cout<<"A fn"<<endl;}
};class B: public A
{
public:virtual void fn(){cout<<"B fn"<<endl;}
};int main(int argc, char* argv[])
{B b1;A a1=(A)b1;A * a2=(A*)&b1;a1.fn();a2->fn();return 0;
}


结果如下:

 


通过调试分析其内存模型如下:


可知,通过A  a1=(A)b1传值时,对象中指向虚函数表的指针__vfptr值不同,但是通过A *a2=(A*)&b1传址操作时,对象中指向虚函数表的指针__vfptr值是相同的,调用的是类B对象的虚函数表中虚函数fn()。注意,对象调用的是哪个类的虚函数就要看类对象的虚函数表中的函数是哪一个。这句话也好理解,a1虚函数表中fn()是A::fn(),a2虚函数表中fn()是B::fn(),所以出现以上结果。

在如下包含父类的父类的继承中:

class A
{
public:
virtual void fn(){cout<<"A fn"<<endl;}
};

class B: public A
{
public:
virtual void fn(){cout<<"B fn"<<endl;}
};

class C: public B
{
public:

};

C c;
A a1=(C)c;
A * a2=(C*)&c;
a1.fn();
a2->fn();

这时,a1虚函数表中fn()为A::fn(),a2虚函数表中fn()为B::fn(),因为类C对象的虚函数表中fn()为B::fn(),a2中指向虚函数表的指针值与类C对象指向虚函数表的指针值相同。

侯捷的书中有句话是这么对它进行解释的:由于(A)b1.fn()是传值而非传地址操作,编译器以所谓的拷贝构造函数把A对象内容复制了一份,使得b1的虚函数表内容与A对象的虚函数表内容相同

看来,得多读圣贤书啊,读懂读透啊!

 

转载于:https://www.cnblogs.com/pangblog/p/3327622.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/421515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android---什么是3G

学习安卓之前我们必须了解什么是3g.这几年随着IT技术的革新。移动互联网已经渐渐的占据了市场的主导地位。而3g技术是移动互联网的一方面体现。那么究竟什么是3g? 3G有三大制式&#xff0c;GSM升级后的WCDMA&#xff0c;CDMA升级后的CDMA2000&#xff0c;以及我国自主开发的TD…

centos7硬盘挂载mysql_centos7 挂载新磁盘

一 、挂载新磁盘查看磁盘[rootlocalhost ~]# fdisk -lDisk /dev/vda: 53.7 GB, 53687091200 bytes, 104857600 sectorsUnits sectors of 1 * 512 512 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk lab…

autolisp 列表 resbuf

有以下 list : (1 2 3 (4 5 6) "Properties" (("id" . 3) ("name" . "hello lisp"))) 要求用: quote cons acutBuildList acutNewRb 方式构造 转载于:https://www.cnblogs.com/pangblog/p/3331246.html

如何看懂php源程序,概述 · thinkphp5.0 源码阅读学习 · 看云

**1 章节简介**概述: 记录框架的文件&#xff0c;类&#xff0c;函数或方法等索引到文章的具体章节&#xff0c;方便查找。框架流程&#xff1a;框架流程的重要文件分析。框架工具&#xff1a;框架自带的重要工具文件分析。框架驱动&#xff1a;框架底层的驱动与扩展目录分析。…

php评论盖楼怎么实现,dedecms评论盖楼实现楼层数,类似腾讯、网易的评论(5.5/5.6版)...

DEDE评论效果&#xff1a;修改后的效果&#xff1a;修改步骤一、织梦dedecms5.5版本(5.6版本请往下看)1、修改/plus/feedback_ajax.php文件的第131行(如果你没改过)下面是修改之前的代码&#xff1a;$qmsg {quote}{title}.$row[username]. 的原帖&#xff1a;{/title}{content…

Nokia 920全部CODE

code码都是7位&#xff0c;我是从别的地方copy过来的&#xff0c;code码后面带了些乱码懒得删了&#xff0c;自己数7位code就是了。 RM-820 NDT AMERICA ATT White 059N5T3RM-820 NDT AMERICA ATT Yellow 059N5T5RM-820 NDT AMERICA ATT Black 059L848RM-…

datagridview绑定与详细说明 (搜集)

1、实现一个用于处理数据库教程数据检索的详细信息的方法。 下面的代码示例实现一个 getdata 方法&#xff0c;该方法对一个 sqldataadapter 组件进行初始化&#xff0c;并使用该组件填充 datatable。 然后&#xff0c;将 datatable 绑定到 bindingsource 组件。请确保将 conne…

matlab显示二值直方图,图像灰度变换、二值化、直方图

1、灰度变换1)灰度图的线性变换Gnew Fa * Gold Fb。Fa为斜线的斜率&#xff0c;Fb为y轴上的截距。Fa>1 输出图像的对比度变大&#xff0c;否则变小。Fa1 Fb≠0时&#xff0c;图像的灰度上移或下移&#xff0c;效果为图像变亮或变暗。Fa-1&#xff0c;Fb255时&#xff0c;发…

Delphi XE2 之 FireMonkey 入门(13) - 动画(下)

TAnimation 类的主要成员: protectedfunction NormalizedTime: Single; //procedure ProcessAnimation; virtual; //其子类们主要通过覆盖此方法来实现不同的动画procedure Loaded; override; // publicprocedure Start; virtual; //播放procedure…

mysql 触发器 插入或者更新,MySQL 在触发器里中断记录的插入或更新?

下面是一种实现的方法。思路就是想办法在触发器中利用一个出错的语句来中断代码的执行。mysql> create table t_control(id int primary key);Query OK, 0 rows affected (0.11 sec)mysql> insert into t_control values (1);Query OK, 1 row affected (0.05 sec)mysql&g…

BZOJ 1601 [Usaco2008 Oct]灌水 (最小生成树)

题意 Farmer John已经决定把水灌到他的n(1<n<300)块农田&#xff0c;农田被数字1到n标记。把一块土地进行灌水有两种方法&#xff0c;从其他农田饮水&#xff0c;或者这块土地建造水库。 建造一个水库需要花费Wi(1<Wi<100000),连接两块土地需要花费Pij(1<pij<…

matlab mxarray array,[Matlab]MxArray与MwArray使用区别

引子在外部编程语言与matlab的交互中&#xff0c;Array是最单元的交互元素&#xff0c;怎么都绕不过去。在matlab提供的Array接口有两个&#xff0c;一个是C的MxArray, 另一个是Cpp(C)的MwArray.看下两着的分别介绍&#xff1a;mxArray&#xff1a;Matlab C 函数库的结构体mwAr…

NSARRAY的 内存管理

一个对象加入到nsarray里内存计数器会1,当这个nsarrayrelease的时候,回自动减1,程序员不需要管理这方面的内存.转载于:https://www.cnblogs.com/gm-lotus/p/3349509.html

blender怎么移动骨骼,Blender学习笔记-(015)创建骨骼绑定及权重绘制操作详解

骨骼创建绑定具体操作如下&#xff1a;1&#xff1a; 【ShiftA】创建基础骨骼。(也可以通过打开Blender的插件Rigging&#xff1a;Rigify&#xff0c;生成自定义骨骼)2&#xff1a;点击骨骼&#xff0c;按【Tab】键进入编辑模式&#xff0c;选中创建骨骼端&#xff0c;按【E】拖…