虚函数

【转】gdb typeid 详解

落花浮王杯 提交于 2019-11-27 04:58:29
在揭开typeid神秘面纱之前,我们先来了解一下 RTTI (Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。 dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的转换操作符static_cast,因为这不是本文的讨论重点,所以这里不再详述,感兴趣的可以自行查阅资料。下面就开始今天我们的话题:typeid。 typeid 是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为 type_info 的标准库类型的对象的引用(在头文件typeinfo中定义,稍后我们看一下vs和gcc库里面的源码),它的表达式有下图两种形式。 如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。 ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的

理解虚函数

邮差的信 提交于 2019-11-27 01:25:35
1、虚函数实现了运行时多态,他是如何实现的呢? 2、含有虚函数的对象,内部有一个vptr(virtual table pointer),指向虚函数表的指针。 3、含有虚函数的类有一个vtbl(virtual table),是一个数组,内部包含的是一组函数指针。 4、每个对象都有一个自己的vptr,类的所有对象共享vtbl 5、vtbl包含一组函数指针,这些函数指针指向虚函数,虚函数包括:   a、对于父类的虚函数,如果没有重写,包含父类的虚函数;   b、对于父类的虚函数,如果重写了,包含自身重写后的函数;   c、自身中,新创建的虚函数。 6、另外,运行时是如何获取对象的类型的?   在类的虚方法表中还有一个函数指针,表明类的名称。对象通过vptr,找到vtbl,然后找到类的名称,也就是对象的类型。 转载于:https://www.cnblogs.com/nzbbody/p/3382990.html 来源: https://blog.csdn.net/weixin_30568715/article/details/99234467

C++继承、多态与虚表

拟墨画扇 提交于 2019-11-26 23:54:56
继承 继承的一般形式 子类继承父类,是全盘继承,将父类所有的东西都继承给子类,除了父类的生死,就是父类的构造和析构是不能继承的。 继承的访问权限从两方面看: 1.对象:对象只能直接访问类中公有方法和成员。 2.继承的子类 私有继承就终止了父类再往下继承的能力 c++默认继承为私有继承 像以下程序 class D :public B1 ,public B2,public B3 公有继承B1,B2,B3 class D :public B1,B2,B3; 公有继承B1,私有继承B2,B3 继承是按照继承的顺序,和构造函数的初始化顺序无关,看以下程序 如果,子类中有对象成员,构造顺序是:1.父类,2.对象成员,3.自己 如果父类中有虚基类,应该先构造虚基类 虚基类 虚基类主要解决菱形继承问题,有以下程序 继承模型为: 内存模型: 如果对父类的x进行赋值,如下程序,会引发错误,编译器会报错,因为继承了两份,会产生二义性 如果指定访问A1还是A2就不会报错 内存中只为A1的成员x赋值了 如果希望来自父类的x在子类中只有1份 那么就要用虚拟继承 对于虚继承来的基类,又叫做虚基类 现在对cc.c进行赋值 A1和A2对象中的x成员都变成100 如果不是虚拟机成A1和A2继承来的x各自是各自的空间 虚继承让子类只保持父类的一份成员拷贝,A1和A2的继承的成员的空间是一个

C/C++的内存对齐

无人久伴 提交于 2019-11-26 22:13:45
1、内存对齐之pragma pack语法 语法:#pragma pack( [show] | [push | pop] [, identifier], n ) 作用:指定结构,联合和类的包对齐方式(pack alignment),可以通知给编译器传递预编译指令而改变对指定数据的对齐方法 举个例子如下: 2、基本数据类型所占用内存大小 3、 静态变量static 静态变量 的存放位置与结构体实例的存储地址无关,是 单独存放在静态数据区的,因此用siezof计算其大小时没有将静态成员所占的空间计算进来。 4、 类 空类是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址。 (一)类内部的成员变量: 普通的变量要占用内存,但是要注意对齐原则(这点和struct类型很相似)。 static修饰的静态变量不占用内容,原因是编译器将其放在全局变量区。 (二)类内部的成员函数: 普通函数不占用内存。 虚函数要占用4个字节,用来指定虚函数的虚拟函数表的入口地址。所以一个类的虚函数所占用的地址是不变的,和虚函数的个数是没有关系的 5、子类 子类所占内存大小是父类+自身成员变量的值。特别注意的是,子类与父类共享同一个虚函数指针,因此当子类新声明一个虚函数时,不必再保存虚函数表指针入口。 来源: https://www.cnblogs.com/mazhimazhi/p

虚函数、纯虚函数详解【转载】

蹲街弑〆低调 提交于 2019-11-26 18:35:56
原文链接 纯虚函数的作用 在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的 派生类 去做。 1.首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数。定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。 定义一个函数为纯虚函数,才代表函数没有被实现。定义他是为了实现一个接口,起到一个规范的作用,规范继承这个。类的程序员必须实现这个函数。 2.关于实例化一个类: 有纯虚函数的类是不可能生成类对象的,如果没有纯虚函数则可以。比如: class CA { public: virtual void fun() = 0; // 说明fun函数为纯虚函数 virtual void fun1(); }; class CB { public: virtual void fun(); virtual void fun1(); }; // CA,CB类的实现 ... void main() { CA a; // 不允许,因为类CA中有纯虚函数 CB b; // 可以,因为类CB中没有纯虚函数 ... } 3.虚函数在多态中间的使用: 多态一般就是通过指向基类的指针来实现的。 4.有一点你必须明白,就是用父类的指针在运行时刻来调用子类: 例如,有个函数是这样的: void animal::fun1(animal *maybedog

C++虚函数详解

和自甴很熟 提交于 2019-11-26 18:31:30
摘自: http://zhidao.baidu.com/question/32424351.html 虚函数联系到多态,多态联系到继承。所以本文中都是在继承层次上做文章。没了继承,什么都没得谈。 下面是对C++的虚函数这玩意儿的理解。 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。下面来看一段简单的代码 class A{ public : void print(){ cout<<”This is A”<< endl;} }; class B: public A{ public : void print(){ cout<<”This is B”<< endl;} }; int main(){ // 为了在以后便于区分,我这段main()代码叫做main1 A a; B b; a.print(); b.print(); } 通过class A和class B的print()这个接口,可以看出这两个class因个体的差异而采用了不同的策略,输出的结果也是我们预料中的,分别是This is A和This is B

c++知识点总结3

强颜欢笑 提交于 2019-11-26 17:30:27
http://akaedu.github.io/book/ week1 引用 :相当于变量的别名。下面r和n就相当于同一回事 int n=4; int &r=n; 引用做函数参数: void swap(int &a, int &b){ //a等价于n1, b等价于n2 int tmp; tmp=a; a=b; b=tmp; } int n1, n2; swap(n1, n2); const int &r=n; //不能通过常引用r来修改n的内容。 const const int MAXAL=23; const char* NAME="pentium"; int n; const int* p=&n; //不能通过常量指针p来修改n的内容int* q=p; //不能将常量指针赋给非常量指针,反之可以 void func(const char* p){ .... 不能提供常量指针p修改内容 } 动态内存分配 int *pn=new int; *pn=555; //动态分配出sizeof(int)这么大的内存,并将其起始地址返回给pn int *pm=new int[6]; pm[5]=666; //动态分配数组//new出来的对象必须手动delete。否则即使运行结束了系统也不会自行销毁 delete pn; delete[] pm; inline:内联函数

CLion报错解决:allocating an object of abstract class type--unimplemented pure virtual method

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-26 13:59:33
在用CLion写代码时遇到了这个报错: allocating an object of abstract class type '...' unimplemented pure virtual method '...' in '...' 这个报错的意思是派生类有没有实现的虚函数,所以是抽象类。 我感觉这个报错有问题,因为我的派生类已经实现了父类的虚函数。 然后我想到一件事:在函数后加上关键字 override 表示重载。 在加上关键字 override 后,clion报错了。 我仔细观察,发现是因为参数中没有 & !!! 来源: https://blog.csdn.net/zhangpeterx/article/details/98881520

C++ RTTI

梦想的初衷 提交于 2019-11-26 10:33:21
1.RTTI RTTI的英文全部意思为Run-Time Type Identification,意思为“运行时类型判断”。RTTI的原理为对某一范型或者接口类型,在运行时再判断该类型或者接口的类型,然后运行对应类型的功能函数。 RTTI的类型的运用,在各种语言中广泛运用;对于JAVA来说,RTTI甚至被号称为JAVA的多态机制的基础。 2.C++中的RTTI 在C++中,RTTI的提出是在1993年,由Stroustrup B.提出(Stroustrup B., “Run-Time Type Identification for C++”, Usenix C++ C onference, Portland, 1993. )。但RTTI的由于其他类型判断会造成低效率,造成部分编译器对RTTI支持性不好。VC++原来一直是不支持RTTI的。在华为的编码规范中,强制要求不用RTTI的写法。这造成了即使是资深C_++程序员,也可能不了解RTTI机制。 3.C++中都RTTI实现 在C++中,RTTI机制是通过虚函数表来实现的。在C++中,虚函数表和虚指针同时也是多态机制的基础。从这个意义上来说,RTTI一开始就和多态和虚函数紧密相关。在C++的RTTI中,是一定要有virtual关键字和虚函数的。 与仅仅的所谓多态属性不同的是,RTTI实现,需要三个元素: 1)dynamic_cast

C++语法小记---经典问题之一(malloc和new的纠缠)

五迷三道 提交于 2019-11-26 02:32:09
malloc和new以及free和delete的区分 new和malloc以及delete和free的区别 new和delete是C++的关键字,malloc和free是库函数 new和delete会先调用构造函数和析构函数,然后释放内存,malloc和free直接就是释放内存 构造函数和析构函数能不能是虚函数 构造函数不能是虚函数:因为构造函数执行完毕之后,虚函数表才会建立 析构函数建议设计成虚函数(因为析构函数在对象销毁之前被调用,此时析构函数没被销毁),这样可以从子类向上依次析构,防止内存泄露 构造函数和析构函数中,调用虚函数,永远不发生多态,只调用本类的函数 来源: https://www.cnblogs.com/chusiyong/p/11315354.html