简单情况:

#include<iostream>
using namespace std;
class A
{
public:
virtual void foo()
{
cout << "virtual void foo()" << endl;
}
}; int main()
{
//通过对象调用,会当成普通成员函数来看待。
A a;
a.foo();
cout << "---------------------" << endl;
A *b = new A();
b->foo();
//编译器视角
/*
((*(b->vptr))[0])();
通过虚函数表指针调用
*/
while (1);
return 0;
}

总结:

1.如果通过对象调用虚函数,编译器直接找到虚函数的地址。

2.对于虚函数和成员函数,编译器都会隐式的传入this指针。

3.对于指针和引用的形式来调用虚函数,编译器走的则是虚函数表的路线。

4.无论是成员函数还是虚函数,他的地址都是在编译期间就已经确定下来了,接下来就看你怎么去找到这个虚函数的地址,可以直接找,也可以通过虚函数表.

复杂情况以及静态成员函数的调用形式:

#include<iostream>
using namespace std;
class A
{
public:
virtual void foo()
{
cout << "virtual void foo()" << endl;
//foo2();//如果虚函数里面这么调用还是会通过虚函数表找到虚函数的地址,所以为了效率,通过类调用(因为在函数内部,所以接下来通过类调用这个this指针编译器可以找的到)
/*
既然在外部已经进入到该虚函数内部了,说明该对象是生成了的,也就是这个this指针存在了
所以接下来的A::foo2();调用会成功,如果在main函数中直接调用A::foo1(),肯定失败,因为编译器隐式传进去的形参this根本就找不到
*/
A::foo2();
}
virtual void foo1()
{
cout << "virtual void foo1()" << endl;
}
static void foo2()
{
cout << "virtual void foo2()" << endl;
}
void aa()
{
cout << "fds" << endl;
}
int data = 3;
};
int main()
{
//如果想让非成员函数像静态成员函数一样被调用。
((A*)0)->aa();//前提是函数体中不能用到隐式传进去的0指针。
/*
对于成员函数aa(),编译器会隐式的传进去0指针,这个0指针实际上里面并没有保存类A的内容,作用仅仅是用来调用该成员函数,类似于:A*p;
p->aa();只是用了一种诡异的手法将这两步进行合并,再调用。
不管是0还是其他的地址,都无所谓,只要用不到那个指针就行,比如 ((A*)899980)->aa();同样也能正常运行,因为前面那个地址仅仅是生成A类型的指针。
如果写成cout<<((A*)0)->data来打印里面的数据成员就错了,因为0地址里面实际并没有保存真正的类A的内容。
*/ //对于静态的成员函数,它不依赖于类对象,所以编译器并不会给他隐式的传进去this指针。
//所以可以直接用类成面来调用。
A::foo2(); //对于虚函数,通过对象调用相当于普通成员函数的调用,用指针和用引用调用则是通过虚函数表来找到对应的虚函数。
/*A ss;
//ss.foo(); cout<<"通过虚函数表找到虚函数的地址"<<endl;
A&p = ss;
p.foo(); A*p=new A();
p->foo(); A&cc = *p;
cc.foo();
*/ /*
普通的成员函数和虚函数在调用的时候编译器都会隐式的传入this指针,而对于静态函数则例外。
*/ while (1);
return 0;
}

C++虚函数和静态函数调用方式的更多相关文章

  1. C++继承-重载-多态-虚函数

    C++ 继承 基类 & 派生类 一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数.定义一个派生类,我们使用一个类派生列表来指定基类.类派生列表以一个或多个基类命名,形式如下: ...

  2. C++多态性----运算符重载与虚函数

    一.多态性 ①概述:多态是指同样的消息被不同类型的对象接收时导致的不同行为. ②类型: 可以分为四类:重载多态.强制多态.包含多态.参数多态. ------------------------ --- ...

  3. C++多态性与虚函数

    派生一个类的原因并非总是为了继承或是添加新的成员,有时是为了重新定义基类的成员,使得基类成员“获得新生”.面向对象的程序设计真正的力量不仅仅是继承,而且还在于允许派生类对象像基类对象一样处理,其核心机 ...

  4. C++ 系列:虚函数

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  5. C++ - 虚基类、虚函数与纯虚函数

    虚基类       在说明其作用前先看一段代码 class A{public:    int iValue;}; class B:public A{public:    void bPrintf(){ ...

  6. C++ Primer--虚函数与纯虚函数的区别

    首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数. 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数. 定义一个函数为纯虚函数,才代表函数没有被实现. 定义纯虚函数是为了实 ...

  7. C++中虚函数的作用

    一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Po ...

  8. C++中虚函数的作用是什么?它应该怎么用呢?

    虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...

  9. 【C++】C++中的虚函数与纯虚函数

    C++中的虚函数 先来看一下实际的场景,就很容易明白为什么要引入虚函数的概念.假设我们有一个基类Base,Base中有一个方法eat:有一个派生类Derived从基类继承来,并且覆盖(Override ...

随机推荐

  1. MIUI12.5扫码之后无法连接MIUI+,显示连接失败

    设置-应用设置-应用管理-小米互联通信服务(如果没有找到,进行搜索即可)-清除数据 重新扫码连接就可以连上了 (感觉不怎么样,不知道是不是我网卡,用起来卡卡的...)

  2. Python实现北邮人论坛模拟登录

    推荐去我的博客里查看这篇文章,效果更佳: http://fuxuemingzhu.cn/2017/08/12/byrbbs-login/ 模拟登录北邮人论坛可能是每个学着写爬虫的北邮人必备技能了.在网 ...

  3. 【LeetCode】846. Hand of Straights 解题报告(Python & C+)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  4. 【剑指Offer】把数组排成最小的数 解题报告(Python)

    [剑指Offer]把数组排成最小的数 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...

  5. hdu 1430 (BFS 康托展开 或 map )

    第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢. 然后想到用map函数,就8!个不同的排列,换成字符串用map标记.然后又交一发果断超时,伤心,最恨超时,还不如来个 ...

  6. B. Recover the String

    B. Recover the String time limit per test 1 second memory limit per test 256 megabytes input standar ...

  7. Arm64架构下静态编译Nginx

    这段时间,我一直忙于将 Rainbond 源码构建模块移植到 Arm64/aarch64 架构中.这一源码构建模块可以将指定代码仓库中包含的源码,拉取构建成为容器镜像,在各种容器平台中运行.目前支持的 ...

  8. 「双串最长公共子串」SP1811 LCS - Longest Common Substring

    知识点: SAM,SA,单调栈,Hash 原题面 Luogu 来自 poj 的双倍经验 简述 给定两字符串 \(S_1, S_2\),求它们的最长公共子串长度. \(|S_1|,|S_2|\le 2. ...

  9. Google Chrome调整控制台的位置

    众所周知,控制台是开发必备的工具,学会流畅的使用控制台会给我们的开发带来不一样的体验,但是控制台的位置有时却是困扰我们的一件事,控制台默认是在浏览器内,有时十分妨碍我们,那么有没有什么办法修改控制台的 ...

  10. Android开发 PorgressBar(进度条)的使用

    圆环进度条(默认)和水平进度条: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...