虚函数

C++中的显示类型转换

ε祈祈猫儿з 提交于 2020-01-04 05:40:24
C++中显示转换也成为强制类型转换(cast),有四种:static_cast、dynamic_cast、const_cast、reinterpret_cast。命名的强制类型转换符号一般形式如下: cast_name<type>(expression); 以下分别介绍 一、static_cast 任何具有明确定义的类型转换,只要不包含底层const都可以使用static_cast。好吧这句话我不是很懂,换句话:编译器隐式执行的任何类型转换都可以由static_cast显示完成。也就是说,两类型之间可以发生隐式的转换,就可以用static_cast显示转换,有点意思。但要知道的是C++基本类型的指针之间不含有隐式转换(void*除外、const的有些也是可以的),需要 显示转换 。什么意思?如下: double d=3.14; int i=d; //编译器的隐式转换,等价于下面这条语句 int i=static_cast<int>(d); /*指针之间的转换*/ char str[]="good"; char *ptr=str; int *p=static_cast<int *>(ptr); //编译错误,两者之间的转换要显式,如下 int *p=(int *)(ptr); 仅当类型之间可隐式转换时(除类层次见的下行转换以外),static_cast的转换才是合法的,否则将出错。

c++中为什么可以通过指针或引用实现多态,而不可以通过对象呢?

ぐ巨炮叔叔 提交于 2020-01-03 17:28:41
目录 一、类对象的存储方式: 二、无论通过对象还是指针,能使用的方法只与它们静态类型有关。 三、 不同类型的指针有什么区别? 四、 指针与引用来实现多态 五、对象不能实现多态 引言: 在c++中司空见惯的事情就是:可以通过指针和引用可以实现多态,而对象不可以。 那为什么?让我们来解开这神秘的暗纱!转载自:https://www.cnblogs.com/yinheyi/p/10525543.html 一、类对象的存储方式: 在一个类的实例中,只会存放非静态的成员变量。 如果该类中存在虚函数的话,再多加一个指向虚函数列表指针—vptr。 例如声明如下两个类,并分别实例化两个对象,它们的内存分配大致如下:(vptr具体在什么位置,与编译器有关,大多数都在开始处) class base { public: virtual ~base() {}; virtual string GetName() { return "base"; } GetA(); int a; }; class derived : public base { public: virtual ~derived() {}; virtual string GetName() { return "derived";} GetB(); int b; }; base B1, B2; derived D1, D2; 内存分布大致如下:

c++虚函数详解(你肯定懂了)

孤者浪人 提交于 2020-01-01 17:29:57
前言 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。 关于虚函数的使用方法,我在这里不做过多的阐述。大家可以看看相关的C++的书籍。在这篇文章中,我只想从虚函数的实现机制上面为大家 一个清晰的剖析。 当然,相同的文章在网上也出现过一些了,但我总感觉这些文章不是很容易阅读,大段大段的代码,没有图片,没有详细的说明,没有比较,没有举一反三。不利于学习和阅读,所以这是我想写下这篇文章的原因。也希望大家多给我提意见。 言归正传,让我们一起进入虚函数的世界。 虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样

单继承、多继承、菱形继承的虚函数表

自古美人都是妖i 提交于 2020-01-01 13:06:49
文章目录 前言 问题 测试环境 开始测试 无虚函数简单类结构 包含虚函数的类结构 单继承 多继承 菱形继承 虚继承 总结 前言 最近被问到一个关于多继承虚函数表的问题,当时回答是可能存在多个虚函数表,应该是顺序排列的,但具体怎么排列还是有些疑惑的,回答的时候到有点儿心虚。之后查了资料,做了简单的实验,可以确定的是对于继承了多个含有虚函数基类的子类来说,指向虚函数表的指针应该不止一个。 问题 虚函数表的问题是从C++多态的概念引出的,要想实现多态有3个条件: 存在继承:没有继承就没有多态(运行时),在多态中必须存在有继承关系的父类和子类。 重写函数:父类中需要定义带有 virtual 关键字的函数,而在子类中重写一个名字和参数与父类中定义完全相同的函数。 向上转型:将父类的指针和引用指向子类的对象。 满足以上三个条件,当使用父类的指针调用带有 virtual 关键字的函数时,就会产生多态行为。 实现这种多态表现的核心内容就是虚函数表,对于带有 virtual 关键字的函数地址会被放入一个表格,而在类中会有一个指向虚函数表的指针指向这个表格,表明这个表格属于类的一部分。 对于父类来说,这个表格中都是自己类的虚函数,而对于子类来说,首先这个虚函数表包含父类中所有的虚函数,当子类重写某个虚函数时就会用子类重写后的函数地址替换原来父类中定义的函数地址

关于C++虚函数,纯虚函数以及模板等重要概念的深入讨论(一)

不羁岁月 提交于 2019-12-28 09:33:33
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1.虚函数 虚函数主要利用在多态的实现上,当基类的成员函数为虚函数时,它的子类函数如果也实现了这个虚函数,那么就可以实现多态的功能。 // Test1.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "iostream" using namespace std; class A { private: int valueA; public: A(); A(int value); ~A(); virtual void print(); }; //The class A realize. A::A() { valueA = 0; } A::A(int value) { valueA = value; } A::~A(){} void A::print() { cout << "This is A print and Value is :" << valueA <<endl; } class B:public A { private: int valueB; public: B(); B(int value); ~B(); void print(); void draw(); }; /

c++之关键字:final与override

帅比萌擦擦* 提交于 2019-12-27 06:03:02
说明: final与override脱离了虚函数均无效,所以final与override都是用于修饰虚函数。 一:final final用于修改虚函数不能被重写。 二:override override用于修饰虚函数必须被声明。 举个例子1: class live { public : virtual void sleep ( ) = 0 ; //声明这是一个纯虚函数 } ; class people : public { public : void sleep ( ) override { std :: cout << "sleep()" << std :: endl ; } } 以上编译是OK的overide声明的sleep()会去检测live的纯虚函数sleep()是否存在,不存在就报错; 举个例子2: class live { public : virtual void sleep ( ) final ; //声明这是不可重写的纯虚函数 } ; class people : public { public : void sleep ( ) { std :: cout << "sleep()" << std :: endl ; //这里就会报错 } } 以上编译是不行的,final什么存虚函数是不可重写的; 来源: CSDN 作者: var.zhou 链接: https:/

继承和虚函数

耗尽温柔 提交于 2019-12-25 01:30:04
虚函数 特征 1.构造和析构中会填写虚表指针 先调用父类构造,先填写父类虚表指针,再执行父类构造函数体 后调用子类构造,填写子类虚表指针,执行子类构造函数体 析构与上述相反(先子类,再父类) 2.虚表特征 虚表存放在只读数据区 虚表中每个成员都是成员函数指针 3.以填写虚表为界限 填写虚表上面是初始化列表 填写虚表下面是构造/析构函数体 4.当有虚表的时候,默认就会提供构造 其他补充 1.如何快速判断一个带有虚函数的类的继承层次? 在虚表指针的地方下硬件写入断点 断点来N次,说明有N-1个父类,减一因为自己也会填一次虚表指针 2.构造析构里调用虚函数会如何? 多态会失效 原因:防止父类调用到子类虚函数,子类在未构造的情形下,会调用到未初始化的资源 编译器优化两种方案: 构造或析构里调用虚函数为直接调用call address(直接绑定地址) 构造或析构里调用虚函数,但仍为本类的虚函数(因为虚表指针此时指向的虚表是自己的) 来源: CSDN 作者: code_greenhand 链接: https://blog.csdn.net/qq_35426012/article/details/103690290

跟我一起学习C++虚函数--第五篇

懵懂的女人 提交于 2019-12-24 14:40:02
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 在前一篇,我们讨论了在多重继承情况下,具有虚函数的类的内存布局情况。本篇将进一步探索在多重虚拟继承情况下的内存布局情况。 在讨论多重虚拟继承前,我们先对《 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局 》中的例子进行扩充。先看看带有虚函数的单一虚拟继承情况下类的内存布局。 先看例子: #include <iostream> using namespace std; class Top { public: virtual void x(){cout << "top x" << endl;} virtual void print0(){cout << "top print" << endl;} public: int a; }; class Left:virtual public Top { public: virtual void x(){cout << "left x" << endl;} virtual void print1(){cout << "left print" << endl;} public: int b; }; int main() { /*first part*/ cout << sizeof(Top) << "\t" << sizeof(Left) << endl;//输出:8

跟我一起学习C++虚函数--第四篇

无人久伴 提交于 2019-12-24 14:24:18
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 在前一篇,我们讨论了在多 继承情 况下,具有虚函数的类的内存布局情况。本篇将进一步探索在多重继承,即具有重复继承的情况下的内存布局情况。在阅读本篇和下一篇之前,建议先阅读本博客另一篇博文《 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局 》。 先说一点题外话,细心的读者可能会发现,我们在探索不同情况下类的内存布局时,总是先通过查看类的大小以及其中各个成员变量的地址来进行分析,然后再具体定位某一位置的值。从最原始的内存中的对象分布,我们可以获得最深入最有效的理解。 OK,请看例子: #include <iostream> using namespace std; class Top { public: virtual void x(){cout << "top x" << endl;} virtual void print0(){cout << "top print" << endl;} public: int a; }; class Left:public Top { public: virtual void y(){cout << "left y" << endl;} virtual void print1(){cout << "left print" << endl;} public: int b;

C++对象模型:单继承,多继承,虚继承

泄露秘密 提交于 2019-12-24 14:13:08
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分。 对于各种支持的底层实现机制。 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 class data members:static和nonstatic class data functions:static、nonstatic和virtual 比如: class Base { public: Base(int i) :baseI(i){}; int getI(){ return baseI; } static void countI(){}; virtual void print(void){ cout << "Base::print()"; } virtual ~Base(){} private: int baseI; static int baseS; }; 对象模型分类 简单对象模型 :这个模型非常地简单粗暴。在该模型下,对象由一系列的指针组成,每一个指针都指向一个数据成员或成员函数,也即是说,每个数据成员和成员函数在类中所占的大小是相同的,都为一个指针的大小。这样有个好处——很容易算出对象的大小,不过赔上的是空间和执行期效率。所以这种对象模型并没有被用于实际产品上。 表格驱动对象模型