虚函数

Interview_C++_day2

青春壹個敷衍的年華 提交于 2020-02-08 19:43:23
函数指针 在编译过程中,每一个函数都有一个入口地址,而函数指针就是指向该入口地址的指针。 #include<iostream> using namespace std; void fun1(int x) { cout << x << endl; } void fun2(int x) { cout << x+x <<endl; } int main() { void (*pf)(int); pf = fun1; pf(222); pf = fun2; pf(222); } 多态性和虚函数(virtual) 静态多态主要表现为重载,在编译时就确定了。 动态多态的基础是虚函数机制,在运行期间动态绑定,决定了基类调用哪个函数。 #include<iostream> using namespace std; class Shape { public: void show() { // 未定义为虚函数 cout << "Shape::show()" << endl; } void virtual show() { // 定义为虚函数 cout << "Shape::show()" << endl; } }; class Line : public Shape { public: void show() { cout << "Line::show()" << endl; } }; class

静态联编和动态联编

北战南征 提交于 2020-02-07 06:48:38
转载自: http://blog.csdn.net/blucexi/article/details/1253265 联编 就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址,它是计算机程序彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法: 静态联编 和 动态联编 。 静态联编 是指在编译阶段就将函数实现和函数调用关联起来,因此静态联编也叫早绑定,在编译阶段就必须了解所有的函数或模块执行所需要检测的信息,它对函数的选择是基于指向对象的指针(或者引用)的类型,C语言中,所有的联编都是静态联编,据我所知道的,任何一种编译器都支持静态联编(废话)。 动态联编 是指在程序执行的时候才将函数实现和函数调用关联,因此也叫运行时绑定或者晚绑定,动态联编对函数的选择不是基于指针或者引用,而是基于对象类型,不同的对象类型将做出不同的编译结果。C++中一般情况下联编也是静态联编,但是一旦涉及到多态和虚拟函数就必须要使用动态联编了。下面将介绍一下多态。 多态 :字面的含义是具有多种形式或形态。C++多态有两种形式,动态多态和静态多态;动态多态是指一般的多态,是通过类继承和虚函数机制实现的多态;静态多态是通过模板来实现,因为这种多态实在编译时而非运行时,所以称为静态多态。 动态多态例子: #include

C++多态

帅比萌擦擦* 提交于 2020-02-07 02:15:42
多态用一句话来总述就是:父类的指针或者引用指向基类的对象 多态分为两种: 编译时多态(静态多态):函数重载,运算符重载 运行时多态(动态多态):派生类,虚函数 静态多态:函数地址早绑定 动态多态:函数地址晚绑定 子类在构造前必须先构造父类,再构造子类,析构顺序相反 non-virtual函数:你不希望子类重写这个函数(override) virtual函数:你希望子类重写这个函数,且你已经有了默认定义 pure-virtual函数:你希望子类一定要重写这个函数,且你对它没有默认定义 ①构造函数可以设置为虚函数吗? 1.从存储空间角度。 虚函数对应一个vtable,这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。 2,从使用角度 构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3、从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数 ②虚析构函数 如果子类的成员变量有堆区开辟的空间

c++ -- 多态(类)

↘锁芯ラ 提交于 2020-02-07 02:12:58
假期 2020.02 .06 学习资源来源于中国MOOC以及c语言中文网 前言 c++之所以是面向对象的是因为该语言既支持类也支持多态,而多态是什么呢? 定义 多态就是同一个操作作用于不同的对象会产生不同的结果。这个操作一般指的是函数的调用等等。 标准定义 是对于通过基类指针调用基类和派生类中都有的同名、同参数表的虚函数的语句,编译时并不确定要执行的是基类还是派生类的虚函数;而当程序运行到该语句时,如果基类指针指向的是一个基类对象,则基类的虚函数被调用,如果基类指针指向的是一个派生类对象,则派生类的虚函数被调用。这种机制就叫作“多态(polymorphism)”。 虚函数 :在成员函数前加 virtual 即可生成虚函数。注意虚函数只能在类的内部定义成员函数时使用,不能在类外部写成员函数时使用,构造函数与静态成员都不能是虚函数。 多态类 :包含虚函数的类称为“多态类”。 如何构成多态 常判断条件是 有继承关系 继承关系中有同名的虚函数,并且是覆盖关系 存在基类的指针,指向派生类的虚函数,或者引用 那么什么时候声明虚函数呢? 成员函数所在的类是否是基类 成员函数在继承后是否会被新定义或者更改,是的话,需要;否则,不需要。 多态应用 举一个指针类型的例子: 注意:多态的语句调用哪个类的成员函数是在运行时才能确定的,编译时不能确定。多态的函数调用语句被称为是“动态联编”

剑指offer速记

核能气质少年 提交于 2020-02-06 23:00:31
一、 const:如果函数参数是指针,且仅作输入用,则必须在类型前面加上const,以用来防止该指针在函数体内被意外修改。 const在*前表示指针所指的内容固定(不允许*abc="789"),指针的指向可变 const int *abc="123" ;abc="345"; const在*后表示指针本身的指向固定(不允许a++),指针所指的内容可变 char tmp[]="123"; int * const abc=tmp;abc[1]='0'; 二、 C++中,四个与类型转换相关的关键字:static_cast、const_cast、reinterpret_cast、dynamic_cast。 空类型的size是1字节,虽然不包含任何信息但是必须在内存中占有一定空间。添加了构造函数和析构函数size不变。如果有虚函数,会为该类型创建虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针,32位机器上一个指针4字节,64位机器上一个指针8字节 构造函数不能以本类的对象作为唯一参数,以免和复制构造函数相混淆Complex (Complex c) {...} 来源: https://www.cnblogs.com/dzzy/p/12271201.html

C++ 虚函数 纯虚函数

不问归期 提交于 2020-02-06 18:20:41
虚函数与纯虚函数其实是两个概念,而平常我自己接触到的虚函数往往是纯虚函数,开始觉得这个概念无关紧要,后来发现还是需要认真区分为好: 首先虚函数是指在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数。 用法:virtual 函数返回类型 函数名(参数表) {函数体}; 两者的区别: 一·函数申明: 虚函数,在函数的声明(不是定义)语句前加“virtual”, 如 virtual void functions() virtual void setID(int ID){ this->ID=ID;//函数实现 } 纯虚函数,在虚函数后还需要加上“=0”,如 virtual void functions()=0 virtual int getID(void)=0; 二·子类继承: 虚函数,派生类类可自主选择是否要提供一份属于自己的个性化虚函数实现。意思是派生类可以选择不重写基类中的虚函数方法,这样可以避免一定程度上的麻烦。 #include<iostream> using namespace std; class People{ public: virtual void setID(int ID){ this->ID=ID; } int ID; }; class Student:public People{ public: }; int main(){

C++内存模型

岁酱吖の 提交于 2020-02-06 04:59:34
C++内存模型 一文了解所有C++内存的问题 AlexCool 目录 一 C++内存模型 二 C++对象内存模型 三 C++程序运行内存空间模型 四 C++栈内存空间模型 五 C++堆内存空间模型 六 C++内存问题及常用的解决方法 七 C++程序内存性能测试 环境: uname -a Linux alexfeng 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux cat /proc/cpuinfo bugs : bogomips : 4800.52 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual cat /proc/meminfo MemTotal: 4041548 kB(4G) MemFree: 216304 kB MemAvailable: 2870340 kB Buffers: 983360 kB Cached: 1184008 kB SwapCached: 54528 kB GNU gdb (Ubuntu 7.9-1ubuntu1) 7.9 g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2

C++内存模型

不打扰是莪最后的温柔 提交于 2020-02-06 04:06:17
前言 之前阿里面试的时候有个面试官就问了我会不会"什么什么的内存模型",当时自己还不知道这个名词(知道概念,但确确实实不知道叫这个名字.....),所以就回了是问关于大小端存储么?面试官就问下一个问题了..... 后来在《程序员的自我修养》这本书中,看了相关的概念,在这里整理一下: Visual Studio查看虚函数表 在这里首先插一个话题,讲解一下如何查看虚函数表。 我们通过调试去查看变量的分布的时候,会发现只能显示出来基类的虚函数表,而派生类的虚函数表却是被隐藏的;我们想查看这个怎么办?下面是步骤: 先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。近期的VS版本都支持这样配置。 运行程序的话就会自动生成一张虚函数表了: 这个内存结构图分成了两个部分,上面是内存分布,下面是虚表;就可以简单进行查看了。 C++内存模型(内存布局) 内存区域 这部分经友人提醒,可以从C++标准的"内存"概念中出发,后面会更新这部分内容。 HERE C++内存分为5个区域: 堆 heap : 由new分配的内存块,其释放编译器不去管,由我们程序自己控制(一个new对应一个delete)

牛客网笔试题目二

╄→尐↘猪︶ㄣ 提交于 2020-02-05 22:15:31
1.select count(*) from table 表示返回表中包括空行和重复行在内的行数,但是会扫描所有列 select count(1) from table 也是返回表中包括空行和重复行在内的行数,不会扫描所有列,1其实就是表示有多少个符合条件的行,但是此时没有where,所有没条件也就是返回总行数 select count(id) from table 表示返回表中存在该列id的行数,但是该列的值不为空,为空的不计算,所以在此题中是不能用这个,因为tg_email都为空,用主键可以,因为主键肯定不为空 2.调用者发出信息后,必须等待消息处理结束返回后,才能进行后续操作的是 同步消息 3. 1个先进先出队列可以通过1个数组或者1个单向链表来实现,出队和入队的均摊复杂度均为O(1) 1个堆栈可以通过1个数组或者1个单向链表来实现,出栈和入栈的均摊复杂度均为O(1) 1个先进先出队列可以通过2个堆栈来实现,出队和入队的均摊复杂度均为O(1) 4.在一个真实的计算机系统中,资源会损坏或被替换,新的进程会进入和离开系统,新的资源会被购买和添加到系统中。如果用银行家算法控制死锁,下面哪些变化是安全的(不会导致可能的死锁)?答:减少可用资源(资源被从系统中永久性地移出)、增加一个进程的Max(进程需要更多的资源,超过所允许给予的资源) 5

WTL学习记(二):WTL的消息处理链

ε祈祈猫儿з 提交于 2020-02-05 16:03:18
前小节简单介绍了WTL安装注意的一点小的细节并举例简述如何对自己的窗口类添加对消息的响应,这一节主要就WTL如何实现对windows窗口过程函数的封装陈述些自己的理解。 一、ATL对Windows窗口的封装 WTL的基础是ATL。WTL的框架窗口是ATL窗口类的继承。因此,先介绍一下ATL对Windows窗口的封装。 由win32 API 中创建Windows应用程序可以知道创建窗口和窗口工作的逻辑是: 1 定义一个窗口类 2 注册窗口类 3 创建该类窗口并显示和激活该窗口 4 窗口的消息处理逻辑在窗口函数中。(该函数在注册窗口类时指定) 可以得知,对于窗口的封装关键在于怎样封装窗口消息处理机制。怎样将消息传递给相应的类的实例。通常的办法是采用虚函数:将每个消息对应生成一个虚函数,这样,在窗口处理函数中,对于每个消息,都调用其对应的虚函数即可。但带来的问题是类的虚函数表过于庞大。ATL的处理机制是只定义了一个虚函数(ProcessWindowMessage())。 图示ATL封装的类的继承关系图。从图中可以看到有两个最基本的类。一个是CWindow,另一个是CMessageMap。 在ATL类中对窗口过程的实现是CWindowImpl。它派生自CWindow、CMessageMap,CWindows是对Windows的窗口API的一个封装。它把一个Windows句柄封装了起来