c++ 类内部函数调用虚函数
做项目的过程中,碰到一个问题。
问题可以抽象为下面的问题:
普通人吃饭拿筷子,小孩吃饭拿勺子。
class People {
public:
void eat() {
get_util_to_eat();
}
virtual void get_util_to_eat() {
std::cout << "People get chopsticks" << std::endl;
}
};
class Children : public People {
public:
void get_util_to_eat() {
std::cout << "Children get scoop" << std::endl;
}
};
int main() {
People* people = new Children();
people->eat();
return ;
}
输出结果:
Children get scoop
当然这也符合我们的预期。
因为people不是虚函数,所以上述程序调用的是people中的eat方法,这就涉及到一个之前我一直模糊的概念,在一个类方法中调用虚方法,是如何调用的。
这又涉及到之前不得不说的一个问题:
class A {
public:
void print() {
std::cout << "i am A" << std::endl;
}
};
int main() {
A* a = NULL;
a->print();
return ;
}
上述代码会输出什么,按照直观的感觉NULL怎么可能调用方法呢,要出core吧。
但是事实上,输出的是:
i am A
调用类函数的时候,c++编译器并不会管该类是否为空,而是将该类的地址当做this指针传到函数中去。
a->print() 时,在编译器中就相当于print(a)
有因为print中没有用到成员变量的情况,所以自然能很正确的运行。
然后来看下汇编代码就能更理解了。以下是People类内的汇编代码。
void eat() {
0x0000000000400bd2 <+>: push %rbp
0x0000000000400bd3 <+>: mov %rsp,%rbp
0x0000000000400bd6 <+>: sub $0x10,%rsp
0x0000000000400bda <+>: mov %rdi,-0x8(%rbp) //rsp表示第一个参数,也就是类的指针
get_util_to_eat();
0x0000000000400be9 <+>: mov -0x8(%rbp),%rax //将类指针放入rax寄存器中
0x0000000000400bed <+>: mov (%rax),%rax //取首地址值,也就是虚表地址
0x0000000000400bf0 <+>: mov -0x8(%rbp),%rdi //放入rdi中,下次函数调用的时候取参用
0x0000000000400bf4 <+>: mov (%rax),%rax //取出虚表中函数的地址
0x0000000000400bf7 <+>: callq *%rax //调用改函数
总结就是,进入类的非静态成员函数时,会默认携带类的指针(this),然后改函数内用到成员变量、成员方法都等同于在前面加了一个this->
So 回到最初的那个问题,在People::eat中传入的是Chilren的指针,所以调用 get_util_to_eat 时从虚表中取出了Children::get_util_to_eat方法并进行调用。
c++ 类内部函数调用虚函数的更多相关文章
- C++构造函数和析构函数调用虚函数时都不会使用动态联编
先看一个例子: #include <iostream> using namespace std; class A{ public: A() { show(); } virtual void ...
- C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类
类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. //单继承的定义 class B:public A { ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
- 自绘CListCtrl类,重载虚函数DrawItem
//自绘CListCtrl类,重载虚函数DrawItem void CNewListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TOD ...
- 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。
本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...
- C++:抽象基类和纯虚函数的理解
转载地址:http://blog.csdn.net/acs713/article/details/7352440 抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层. ...
- (转)(C++)关于抽象基类和纯虚函数
★抽象类:一个类可以抽象出不同的对象来表达一个抽象的概念和通用的接口,这个类不能实例化(创造)对象. ★纯虚函数(pure virtual):在本类里不能有实现(描述功能),实现需要在子类中实现.例: ...
- C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数
1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并 ...
- C++ 构造函数或析构函数调用虚函数
构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类 ...
随机推荐
- unity-----------------------------关于WheelCollider设置或小车运动的注意事项
转载:Unity3d 汽车物理引擎 WheelCollider总结 WheelCollider总结 写了前面两篇文章,我想总结一下WheelCollider! 让我们能够更清晰的学会物理车的开发! ...
- (转)live555 RTSP Server RTP over TCP BUG
最近碰到一个非常棘手的问题,NVR通过ONVIF协议接入IPC进行录像,在录像时,会发现其中有个别IPC会出现录像断断续续的情况.这种情况很难复现,但是这种情况一旦出现,整个过程会一直持续很长时间,一 ...
- ubuntu -- 安装最新版的nodejs
1.安装最新的nodejs和npm # apt-get update # apt-get install -y python-software-properties software-properti ...
- jquery 插件和后台模板搜集
弹框 alert confirmhttp://www.jq22.com/jquery-info2607 jQuery表格排序筛选插件http://www.jq22.com/jquery-info880 ...
- Linux运维基础命令笔试题--看看你会多少?
老男孩教育linux运维就业班第一周课后学习效果能力上机大考察 (每题10分共130分,过100即可,请给出详细步骤) 1.创建目录/data/oldboy ,并且在该目录下创建文件oldboy.tx ...
- Linux系统设置及基本操作
下面是Linux系统的基本的使用以及系统操作命令,目录结构等等! linux系统的操作方式 图形界面:RHEL6默认使用GNOME桌面环境 伪字符终端: 图形桌面环境中的伪字符终端 对应程序: gn ...
- 各大引擎矩阵的矩阵存储方式 ----行矩阵 or 列矩阵
OpenGL 里面的矩阵 float m[16]; OpenGL中的矩阵是这样的 m[0] m[4] m[8] m[12] m[1] m[5] m[9] m[13] m[2] m[6] m[10] ...
- 设置wetty不需要账号登录便可进行命令行操作
前一篇随笔我们将了Linux怎么安装部署Wetty服务,但是我们看到,在浏览器中输入http://127.0.0.1:3000进行访问的时候,还需要我们输入账号密码进行认证(如下图第一行所示). 但在 ...
- 磁盘IO概念及优化入门知识
在数据库优化和存储规划过程中,总会提到IO的一些重要概念,在这里就详细记录一下,对这个概念的熟悉程度也决定了对数据库与存储优化的理解程度,以下这些概念并非权威文档,权威程度肯定就不能说了. 读/写IO ...
- php解析mpp文件
php没有找到相应的包 Java的mpxj可以实现 所以借助JavaBridge.jar 1.安装jdk,设置环境变量(我的版本jdk1.8.0_131) 2.下载mpjx 在http://www.m ...