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++ 构造函数或析构函数调用虚函数
构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类 ...
随机推荐
- 弹出输入框后,将listview内容遮住,解决方案
转自http://blog.csdn.net/silence_cdsn/article/details/7987063 更改listview的布局属性 之前的布局: <ListView andr ...
- 正则split
string content = "第1行导入失败,失败原因为: <加班原因>字段必填"; string[] resultString = Regex.Split(co ...
- Ubuntu一般软件安装后的路径
Ubuntu一般安装的软件查找路径: computer/usr/local/
- glsl boom
原理: 1.渲染场景到fbo 2.对fbo进行高斯横向,纵向模糊,到新的fbo 3.对两张图进行叠加 模糊后的 效果就这样 给数据加大 <-vertex-> #version varyin ...
- 配置IDEA Scala环境
http://snglw.blog.51cto.com/5832405/1634595
- Hibernate的七种映射关系之七种关联映射(一)
关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用. 一.Hibernate多对一关联映射:就是在“多”的一端加外键,指向“一”的一端. 比如多个学生对应一个班级,多个用户对应一个级 ...
- 如果返回结构体类型变量(named return value optimisation,NRVO) ------ 续
为什么? <More C++ idioms>: 3. Algebraic Hierarchy 程序执行的流程与自己想的不一样: Number Number::makeReal(double ...
- SpringBoot整合cxf发布webService
1. 看看项目结构图 2. cxf的pom依赖 1 <dependency>2 <groupId>org.apache.cxf</groupId>3 <art ...
- synchronized关键字的用法总结
synchronized关键字主要有以下这3种用法: 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁 修饰代 ...
- level 1 -- unit 2 - what 引导的特殊疑问句
特殊疑问句 what 引导的特殊疑问句 常见结构如下: 1. what be sb/sth? 1.1 如 谓语动词是单数is what is your phone number ? what is y ...