虚函数

虚函数练习:交通工具信息

[亡魂溺海] 提交于 2020-02-29 21:19:27
Problem E: 交通工具信息 Description 有一个交通工具类vehicle。将它为 基类派生的有派生小车类car,卡车类truck和轮船类boat。定义这些类,并使其可以显示其各类交通工具的具体信息。 他们包括的信息,有例如以下几种: 1.名字 -----与输入的名字相符合 2.时速(km/h) -----最高时速 3.耗油量(L/100km) -----在经济时速下測得耗油量 小车类: 250km/h 14.8 L/100km 卡车类: 140km/h 18L/100km 轮船类: 50km/h 8.33L/100km Input 输入三个派生类相应名字。 Output 输出相应类型的信息。 Sample Input Mercedes_Benz Transport_truck Boat Sample Output Mercedes_Benz 250km/h 14.8L/100km Transport_truck 140km/h 18L/100km Boat 50km/h 8.33L/100km HINT #include <iostream> #include <string> using namespace std; class Vehicle { public: string name ; public: Vehicle (string h): name(h)

虚函数

守給你的承諾、 提交于 2020-02-29 20:55:47
函数分类 虚函数: 被子类同名函数所覆盖,可分为纯虚函数和普通虚函数。 (1)纯虚函数: virtual void f()=0; 默认情况是只有定义,而无需实现,即只是定义一个接口,同时包含了纯虚函数的类表明该类时一个抽象类,不能定义该类的对象,也就是说该类被定义成基类,是要被继承的,通过继承类来完成基类对象的生成。不能实例化对象。 (2)一般虚函数: virtual void f(){ }; 必须要有函数的实现。 虚函数的 作用 实现“动态联编”,即在程序的运行阶段 动态地选择合适的成员函数 。 实现方式 :在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型,以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。 虚函数的代价 每个虚函数的对象都必须维护一个V表,使用虚函数时都会产生系统开销,若仅是很小的类且不想派生,没必要用。 虚指针 虚函数的实现细节,带有虚函数的类中每个对象都有一个虚指针指向该类的虚函数表。 来源: https://www.cnblogs.com/yujing611033/p/6011454.html

C++多态,虚函数,虚函数表,纯虚函数

旧巷老猫 提交于 2020-02-29 20:55:20
1、多态性 指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。 C++支持两种多态性:编译时多态性,运行时多态性。 a、编译时多态性:通过重载函数实现 ,模板(2次编译) b、运行时多态性:通过虚函数实现。 2、覆盖,隐藏,重载 重载,静态多态,一个类里面 覆盖, 虚函数 ,同参数,同名称,同返回 隐藏 : 1.1 基类非虚函数,子类与父类同名称(可能覆盖一大片父类函数)  1.2 基类非虚函数,派生类声明为virtual ,参数相同,此时virtual关键字失效 2.2 基类虚函数, 派生类不使用virtual, 形参不同,则丢失多态 2.3 基类和派生类都是 虚函数, 形参相同,返回值不同,报错 ////////////////////////// 多态典型应用,抽象工厂模式, /////////////////////////////////////////////////////////// 虚函数表,动态绑定如何实现? 多重继承,一个基类(含虚函数)会有一个虚表指针,继承后,自己的虚函数放在第一个虚表后面。 D:A,B,C; 强转D对象为A,B,C的时候,地址不一样 //////////////////////////////////// 构造函数与析构函数是否能定义为虚函数?能否抛出异常? 构造的时候必须要知道构造的东西结构吧,虚个鸡毛。。

虚函数表

不想你离开。 提交于 2020-02-29 20:55:01
以上述类型为例: void a_fun_1();为基类虚函数,在派生类b中没有重新进行定义; void a_fun_2();为基类虚函数,在派生类b中被重新进行定义;    void b_fun_1();为派生类中新增加的虚函数; 那么基类a和派生类b的虚函数表是这样的: 规则是: 在派生类中,如果没有重新定义基类中的虚函数,将直接从原来虚函数表中继承将信息过来; 在派生类中,如果重新定了基类中的虚函数,那么将用新的虚函数地址覆盖原来的虚函数在虚函数表中的信息; 在派生类中,如果重新增加类虚函数,那么将在虚函数表中插入新的虚函数地址信息; 来源: https://www.cnblogs.com/achao123456/p/9609107.html

C++ Primer 第十五章 面向对象程序设计 15.2 定义基类和派生类 练习和总结

a 夏天 提交于 2020-02-28 22:43:38
基类和派生类是相对的概念,如果类A继承自类B,则类B相对于类A是基类,类A相对于类B是派生类。 15.2 定义基类和派生类 在定义基类时,我们需要将析构函数和需要子类重写的函数定义为 虚函数 , 因为当我们使用指针或者引用调用虚函数时,会根据实际绑定的动态类型来调用基类或者子类的函数。 为什么要这样做? 在定义派生类的时候解释。 之前在修饰类的成员时,我们只使用了private和public,这里还有一个protected用来修饰成员,表示派生类可以直接访问,但是其他用户(类,函数)不能对修饰为protected的成员访问。 15.2.1 定义基类 练习 15.1 使用virtual关键字修饰的函数时虚函数 15.2 用protected修饰的成员,使用类的用户不能直接访问,但是继承该类的派生类可以访问。 使用private修饰的成员,使用这个类的用户不能直接访问,继承该类的派生类也不可以直接访问。 15.3 class Quote { public : Quote ( ) = default ; virtual ~ Quote ( ) = default ; Quote ( const string & s , double p ) : bookNo ( s ) , price ( p ) { } ; virtual double net_price ( std :: size

从Java角度说起C++虚函数

社会主义新天地 提交于 2020-02-28 22:05:16
多态是面向对象的一大特征,接口的多种不同的实现方式即为多态,简而言之 方法的重载与重写 父类对象的引用指向子类对象的实体 在Java中,如果使用我们刚刚所述的,基类引用指向派生类对象实体,那么调用该引用的函数,实际上会调用派生类的函数,给个例子,相信大家会有更加深刻的体会。 public class Test { public static void main ( String [ ] args ) { A test = new B ( ) ; test . foo ( ) ; } } class A { void foo ( ) { System . out . println ( "This is foo() form A" ) ; } } class B extends A { void foo ( ) { System . out . println ( "This is foo() from B" ) ; } } 这段代码最终输出的结果是 This is foo() from B ,相比而言,C++ 默认就不是这种情况了。 当使用关键字 virtual 声明 foo() 为虚函数的时候,才能更好的实现多态,即,父类对象的引用,指向子类对象的实体,这个父类引用调用虚函数,实际调用的是子类的函数,而非父类。也就是说,Java 默认情况下,使用的就是 C++ 中的虚函数。总之

c++虚函数和虚函数表

故事扮演 提交于 2020-02-28 09:55:14
前言 (1)虚基表与虚函数表是两个完全不同的概念 虚基表用来解决继承的二义性(虚基类可以解决)。 虚函数用来实现泛型编程,运行时多态。 (2)虚函数是在基类普通函数前加virtual关键字,是实现多态的基础 (3)虚函数表其实不用我们管这个编译器会帮我们做好 注:无特别说明本文的虚表均指虚函数表 (一) 什么是虚函数表? 虚函数(Virtual Function)是通过一张虚函数表(VirtualTable)来实现的。简称为V-Table。 虚表(virtual table),编译器为每个拥有虚函数的类都建有一张虚函数表,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数 。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。 C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下) (二)含虚函数的单继承 单继承时,派生类中仅有一个虚函数表。这个虚函数表和基类的虚函数表不是一个表(无论派生类有没有重写基类的虚函数),但是如果派生类没有重写基类的虚函数的话,基类和派生类的虚函数表指向的函数地址都是相同的。 #include

构造函数不可虚,析构可以虚

痴心易碎 提交于 2020-02-27 04:41:01
一.什么是虚函数: 可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时, 基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数, 而不是基类中定义的成员函数(只要派生类改写了该成员函数)。 若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都 会调用基类中定义的那个函数。 例 class A { virtual void AAA() { cout<<"这是基类的!"; } }; class a:A { void AAA() { cout<<"这是派生类a!"; } }; 然后你生成a的实例,调用AAA()方法时,程序调用的是a中的AAA,而不是A中的AAA 如果你不定义virtual,在生成a的实例后调用的是基类的AAA() 二.构造函数不可定义为虚函数: 1,从存储空间角度 虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。 2,从使用角度 虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。

构造函数不可虚,析构可以虚

久未见 提交于 2020-02-27 04:34:05
一.什么是虚函数: 可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时, 基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数, 而不是基类中定义的成员函数(只要派生类改写了该成员函数)。 若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都 会调用基类中定义的那个函数。 例 class A { virtual void AAA() { cout<<"这是基类的!"; } }; class a:A { void AAA() { cout<<"这是派生类a!"; } }; 然后你生成a的实例,调用AAA()方法时,程序调用的是a中的AAA,而不是A中的AAA 如果你不定义virtual,在生成a的实例后调用的是基类的AAA() 二.构造函数不可定义为虚函数: 1,从存储空间角度 虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。 2,从使用角度 虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。

构造函数为什么不能为虚函数 & 基类的析构函数为什么要为虚函数

亡梦爱人 提交于 2020-02-27 03:24:15
一、构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的。问题出来了,假设构造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候可以变成调用子类的那个成员函数。而构造函数是在创建对象时自己主动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3. 构造函数不须要是虚函数,也不同意是虚函数,由于创建一个对象时我们总是要明白指定对象的类型,虽然我们可能通过实验室的基类的指针或引用去訪问它但析构却不一定,我们往往通过基类的指针来销毁对象。这时候假设析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。 4. 从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数从实际含义上看,在调用构造函数时还不能确定对象的真实类型(由于子类会调父类的构造函数);并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次