定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。 定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。...那我现在有一个抽象类的对象,我要调用接口,调用哪个? ---- Q5:基类的析构函数为什么要定义成虚函数?...所以在调用基类的析构函数时,派生类对象的数据成员已经销毁,这个时候再调用子类的虚函数没有任何意义。 ---- Q8:静态函数能定义为虚函数吗?...2、虚函数表类似一个数组,类对象中存储vptr指针,指向虚函数表。...每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着该虚函数表的指针(可以认为这是由编译器自动添加到构造函数中的指令完成的)。
没用过,下次可以试试自己写一个名空间,如果是没有名字的名空间,那么只能在包含那个名空间的文件里面使用该名空间内部的内容,类似于,静态变量、函数的集合。...3、调用函数从临时位置获取这个值 返回引用的返回机制是这样的: 1、获取返回值 2、直接将返回值拷贝给调用函数 如果返回值不大,那就不大,如果返回值是一个结构这种比较大的东西,那就比较麻烦了,能明白我意思不...其实他讲低代码的时候,我想起来了QT的UI,只要你会拖控件,就可以做出界面来,代码可以后台自动生成。 而现在又有多少人,是面向百度编程的。...派生类对象包含一个指向独立地址表的指针。如果派生类提供了虚函数的新定义,该函数表将保存新函数的地址;如果派生类没有重新定义虚函数,该vtbl将保存函数原始版本的地址。...如果派生类定义了新的虚函数,则该函数也将被添加到vtbl中。注意,无论类中包含的虚函数是1个还是10个,都只需要在对象中添加1个地址成员,只是表的大小不同而已。
虚函数的定义较为简单,只需要在函数的接口部分加上virtual关键字即可,当虚函数所在类被继承时,派生类会隐含一个基类的虚函数,此时如果基类重新定义这个虚函数,并且和基类的虚函数的参数列表,返回值,函数名都一样...协变也是虚函数重写的特殊情况,三同中返回值可以不同,但是要求返回值必须是一个父子类关系的指针或引用,自己的父类或其他的父类都可以。实际并不常见,大家只要了解一下这个语法就够了。...则派生类也会继承父类的BuyTicket // 建议父类子类都加上virtual // 2.协变:三同中返回值可以不同,但是要求返回值必须是一个父子类关系的指针或引用,自己的父类或其他的父类都可以...我们可以通过对比地址的方式来确定虚表的位置,从代码运行结果就可以看出,虚表地址和代码段的地址较为相近,所以虚表位置极大可能性就是在代码段,另一方面去理解的话,虚函数本质不就是类成员函数吗?...5.静态成员可以是虚函数吗?
继承类似组合的作用,组合是将其他的类作为成员放入类中,而继承则是直接将基类的成员直接继承到派生类中。...,这时候就可以采用覆盖的方式来修改函数的内容,即在派生类中定义的函数的定义方式与基类相同的情况,则派生类中这个函数的内容是派生类中的内容,若是再使用基类中的函数,则可以采用基类::函数名的方式 例:class...其次是虚函数,虚函数其中一个作用便是可以实现多态,在基类中定义一个虚函数格式为: virtual 返回类型 函数名(); 这样有这个基类产生的派生类中可以对virtual后的函数进行定义,但定义时要和基类中定义函数的方式相同...拥有纯虚函数的类就被称为抽象类。纯虚函数的优点是可以先不用定义函数的功能,而是由派生类进行定义即可,另外要注意析构函数可以做虚函数,但是构造函数不可以。...定义方式:virtual 返回类型 函数名()=0; 虚函数可以实现多态,最简单的一个应用则是将派生类引用或传址给基类,这样基类中的虚函数会根据派生类中的对应函数定义来确定函数的功能,主要采用的是传址和引用两个方式
虚函数的重写(也可以叫覆盖): 派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。...但是是有要求的: 基类虚函数必须返回基类对象的指针或引用,派生类虚函数必须返回派生类对象的指针或引用,我们把这种情况称为协变。...另外,这里这里返回的基类派生类的指针或引用也可以是其它继承体系中的基类和派生类。...另外上面说返回的基类派生类的指针或引用也可以是其它继承体系中的基类和派生类,什么意思呢? 那就是这样 这样也是可以的 不过这个协变可能在实际中应用的场景不多。 3....因此结果是B->0 那说到这里我们也顺便来区分一组概念: 4. 接口继承和实现继承 普通函数的继承是一种实现继承,派生类继承了基类的成员函数,可以使用该函数,继承的是函数的实现。
即基类虚函数返回基类对象的指针或者引 用,派生类虚函数返回派生类对象的指针或者引用时,称为协变。...,展现出不同的形态 要达到多态,有两个条件,一个是虚函数覆盖,一个是对象的指针或引用调用虚函数 满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到该对象中取找的(所以多态的条件包括使用基类对象指针或引用去调用...当对象调用虚函数时会先找到虚函数表,通过虚函数表找到对应的虚函数,由此构成多态 inline函数可以是虚函数吗?...答:可以,不过编译器会忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去 静态成员可以是虚函数吗?...答:不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式 无法访问虚函数表,所以静态成员函数无法放进虚函数表。 构造函数可以是虚函数吗?
协变 类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变(基类与派生类虚函数返回值类型不同) 示例: class A {}; class B : public...,展现出不同的形态 要达到多态,有两个条件,一个是虚函数覆盖,一个是对象的指针或引用调用虚函数 满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到该对象中取找的(所以多态的条件包括使用基类对象指针或引用去调用...可以,不过编译器会忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去 静态成员可以是虚函数吗?...不能,因为静态成员函数没有this指针,不能通过对象指针找到其虚函数表,使用类型::成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表 构造函数可以是虚函数吗?...可以,并且最好把基类的析构函数定义成虚函数 当基类指针指向new出来的基类对象或new出来的派生类对象时,需要使用指针进行释放对象,此时需要析构函数为虚函数,保证指针指向的对象成功释放 对象访问普通函数快还是虚函数更快
}; 3.虚函数的重写(覆盖) 派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同) ,称子类的虚函数重写了基类的虚函数。...协变(基类与派生类虚函数返回值类型不同) 派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指 针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变。...这里的父子类的指针或引用甚至还可以是其他的父子类的指针或引用。...答:可以,不过编译器就忽略inline属性,这个函数就不再是 inline,因为虚函数要放到虚表中去。 2. 静态成员可以是虚函数吗?...答:不能,因为静态成员函数没有this指针,使用类型::成员函数 的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表。 3. 构造函数可以是虚函数吗?
(3)使用抽象类时注意: 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。...如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。 抽象类是不能定义对象的。一个纯虚函数不需要(但是可以)被定义。...这就是纯虚函数的作用。 纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。 凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。...例如,绘画程序中,shape作为一个基类可以派生出圆形、矩形、正方形、梯形等, 如果我要求面积总和的话,那么会可以使用一个 shape * 的数组,只要依次调用派生类的area()函数了。...当一个成员函数被声明为虚函数之后,其派生类中同名函数自动成为虚函数,在派生类中重新定义此函数时要求函数名、返回值类型、参数个数和类型全部与基类函数相同。
(但不总是)覆盖它集成的虚函数,如果没有覆盖的话,则该虚函数的行为类似于其他的普通成员,派生类会直接继承其在基类中的版本 派生类可以在它覆盖的函数前适用virtual关键字,但不是非得这么做 C++11...尽管从语法上来说我们可以在派生类构造函数体内给它的共有或受保护的基类成员赋值,但最好不要这么做。 2.3 继承与静态成员 如果基类定义了一个静态成员,则在整个继承体系中只存在该成员的唯一定义。...一般情况下派生类中虚函数返回类型是类本身的指针或引用时,上述规则无效。比如D由B派生而来,则基类的虚函数可以返回B*而派生类的对应函数可以返回D*。...合成拷贝控制与继承 基类或派生类的合成拷贝控制成员与其他合成的构造函数、赋值运算符或析构函数类似:它们对类本身的成员依次进行初始化、赋值或销毁的操作。...另外某些定义基类的方式也可能导致有的派生类成员称为被删除的函数: 如果基类中的默认构造函数、拷贝构造函数、拷贝赋值运算或析构函数是被删除的函数或者不可访问,则派生类中对应的成员将是被删除的,原因是编译器不能使用基类成员来执行派生类对象基类部分的构造
有些时候我们不希望派生类独有的部分被截断,则需要使用类指针来调用重载的函数或使用指针所指的成员。...如果是指针或引用的转换,则只是一个指向的改变 派生类的构造函数需要负责所有成员的初始化,尽管派生类也可以初始化继承来的基类成员,但是这不符合通常的编码思路,派生类一般在构造函数开始的地方调用基类的构造函数...,让基类来初始化自己的成员 派生类可以使用基类的public成员和protected成员 如果基类定义了一个静态成员,那整个继承体系中都只会有这成员的唯一定义,无论派生了多少类这个成员都是唯一实例的,静态成员也同样遵循访问控制原则...,那必须名称和形参都一致,否则编译器会认为这两个函数是独立的,而不会产生覆盖 派生类的虚函数的返回类型也需要与基类一致,除非虚函数的返回类型是类本身的引用或指针时为了多态性会有特例 如果想要保证基类中某个虚函数一定会被覆盖...15.4 抽象基类 我们有时候希望某个基类只用来被继承而不允许被实例化,这时候我们可以给这个基类加入纯虚函数,拥有纯虚函数的基类叫抽象基类,不能被直接创建 纯虚函数的定义方法是在声明函数名的时候函数体类似显式默认构造的写法改写为
多态的定义及实现 多态是类继承时,对象去调用同一个对象产生不同的行为 要构成多态的条件有两个 虚函数的重写 基类的对象或引用调用虚函数 虚函数的重写 什么是虚函数?...虚函数重写的条件 是虚函数,且函数名,返回值的类型,参数类型相同(三同) 三同,但是只有父类写virtual也构成重写 特殊情况: 其他条件相同,返回值的类型为父子对象或指针类型也构成重写——这个也叫做协变...,就可以证明上面我说的了。...printvf((VF*)*(int*)c, 3); return 0; } 直接看结果: 可以看出多继承有多个虚表,子类没有重写的函数放在第一个虚表中 面试常见的问题 inline函数可以是虚函数吗...静态成员可以是虚函数吗? 构造函数,拷贝构造,赋值运算符的重载可以是虚函数吗? 析构函数可以是虚函数吗? 对象访问普通函数快还是虚函数快 虚函数表在什么阶段产生的,存在哪里?
这里简单做一个总结: 在基类的方法声明中使用关键字virtual可以声明虚函数 加上了virtual关键字的函数在基类以及派生类和派生类再派生出来的类中都是虚的 在调用虚函数时,程序将会根据对象的类型执行对应的方法而非引用或指针的类型...友元 友元函数不能是虚函数,因为友元不是类成员,只有成员函数才能是虚函数。 如果我们希望友元函数也能实现类似虚函数的功能, 我们可以在友元函数当中使用虚函数来解决。...没有重新定义 如果派生类当中没有重新定义虚函数,那么将使用该函数的基类版本。如果派生类位于派生链中,如B继承了A,C继承了B这种情况,那么派生类将会使用最新的虚函数版本。...speak,而在子类Human当中也定义了一个需要传入一个string类型的虚函数speak。...C++ Primer当中给出了两条经验规则: 如果重新定义继承的方法,应该保证与原来的原型完全相同,唯一的例外是返回的类型,如果基类返回的是基类的引用或指针,派生类可以改成派生类的引用或指针: class
多态的表现形式一 「派生类的指针」可以赋给「基类指针」; 通过基类指针调用基类和派生类中的同名「虚函数」时: 若该指针指向一个基类的对象,那么被调用是 基类的虚函数; 若该指针指向一个派生类的对象,那么被调用...— — || 03 多态的表现形式二 派生类的对象可以赋给基类「引用」 通过基类引用调用基类和派生类中的同名「虚函数」时: 若该引用引用的是一个基类的对象,那么被调 用是基类的虚函数; 若该引用引用的是一个派生类的对象...假设我把上面的代码转换一下, 大家还觉得输出的是 Base::fun2() 吗?...} } this 指针的作用就是指向成员函数所作用的对象, 所以非静态成员函数中可以直接使用 this 来代表指向该函数作用的对象的指针。...成员函数,所以调用了基类的bye成员函数 ---- — 5 — 多态的实现原理 「多态」的关键在于通过基类指针或引用调用一个虚函数时,编译时不能确定到底调用的是基类还是派生类的函数,运行时才能确定。
如果派生类没有覆盖其基类中的某个虚函数,则该虚函数的行为类似于其他的普通成员,派生类会直接继承其在基类中的版本。 派生类可以在它覆盖的函数前使用 virtual关键字,但不是非得这么做。...即使一个基类指针或引用已经绑定在一个派生类对象上,也不能执行从基类向派生类的转换。可以使用 dynamic_cast执行运行时安全检查或 static_cast来强制覆盖掉编译器的检查工作。...而对于非虚函数的调用是在编译时进行绑定。类似的,通过对象进行的函数(虚函数或非虚函数)调用也在编译时绑定。 一旦某个函数被声明为虚函数,则在所有派生类中它都是虚函数。...而对于派生类中覆盖的虚函数,其形参必须相同,返回类型也要与基类匹配。而当虚函数的返回类型是类本身的指针或引用且可进行类型转换时,也是允许的。 ?...基类的友元在访问派生类成员时不具特殊性,类似的,派生类的友元也不能随意访问基类的成员。但是基类的友元是可以访问内嵌在派生类对象中的基类成员。
封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。...[]会调用每个成员的析构函数 用new分配的内存用delete释放,用new[]分配的内存用delete[]释放 八、STL库用过吗?...,还没有内存空间,更没有虚函数表地址用来调用虚函数即构造函数了 2、析构函数最好声明为虚函数 首先析构函数可以为虚函数,当析构一个指向派生类的基类指针时,最好将基类的析构函数声明为虚函数,否则可以存在内存泄露的问题...因为引用(或指针)既可以指向基类对象也可以指向派生类对象,这一事实是动态绑定的关键。用引用(或指针)调用的虚函数在运行时确定,被调用的函数是引用(或指针)所指的对象的实际类型所定义的。...例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak 3)可以返回类成员的引用,但是最好是const
在C++中,使用关键字class或struct来定义一个类,并使用关键字public、private或protected来指定成员的访问权限。...通过继承,派生类可以继承基类的接口和实现,并且可以添加自己的功能或修改基类的行为。 继承是面对对象的主要特性之一,它使一个类可以从现有类中派生,而不必重新定义一个类。...dynamic_cast用于将基类指针或引用转换为派生类指针或引用,如果转换成功,返回指向派生类的指针或引用;如果转换失败,则返回空指针或抛出bad_cast异常。...只有通过基类指针或引用调用虚函数才能引发动态绑定 虚函数不能声明为静态 如果一个类要做为多态基类,要将析构函数定义为虚函数 虚表指针 虚函数的动态绑定是通过虚表来实现的 包含虚函数的类头4个字节存放指向虚表的指针...派生类中必须实现基类中的纯虚函数,否则被看做一个抽象类 对于一个没有任何接口的类,如果想要将它定义成抽象类,只能将虚构函数声明为纯虚的 通常情况下在基类中纯虚函数不需要实现,例外是纯析构函数要给出实现
2.区分虚表和虚表指针生成阶段 虚表是在编译阶段就生成的了,而虚表指针是在构造函数初始化列表阶段初始化的。这也侧面回答了下一个问题。 3.构造函可以是虚函数吗?...切片: 我们都知道,多态的的条件是虚函数的重写和必须通过基类的指针或者引用调用虚函数。。那么为什么一定是需要基类的指针或引用呢? 先来看看不用指针或引用,也就是使用基类对象来调用虚函数。...内联函数可以写成虚函数,不过写出虚函数后,这个内联函数就不是内联函数了。 6.静态成员可以是虚函数吗?...不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表。 7.析构函数可以虚函数吗? 基类的析构函数最好是虚函数。...另外,纯虚函数可以有函数实体,但是没必要。 抽象类的作用是强制重写虚函数。另外抽象类体现出了接口继承关系 大家如果还有什么问题需要补充的话可以评论告诉我哦!
在派生类中重新定义基类中的虚函数时,可以不用关键字 virtual来修饰这个成员函数 。 虚函数是用关键字virtual修饰的某基类中的protected或public成员函数。...它可以在派生类中重新定义,以形成不同版本。只有在程序的执行过 程中,依据指针具体指向哪个类对象,或依据引用哪个类对象,才能确定激活哪一个版本,实现动态聚束。...关于虚函数,说明以下几点: 1、当在基类中把成员函数定义为虚函数后,在其派生类中定义的虚函数必须与基类中的虚函数同名,参数的类型、顺序、参数的个数必须一一对应,函数的返回的类型也相同。...3、虚函数必须是类的一个成员函数,不能是友元函数,也不能是静态 的成员函数。 4、在派生类中没有重新定义虚函数时,与一般的成员函数一样,当调 用这种派生类对象的虚函数时,则调用其基类中的虚函数。...指向类成员的指针 在C++中可以定义一种特殊的指针,它指向类中的成员函数或类中的数据成员。并 可通过这样的指针来使用类中的数据成员或调用类中的成员函数。
,调用这个类型的成员函数 2、满足多态 -- 看指向的对象的类型,调用这个类型的成员函数 满足多态: 不满足多态: 思考:你可能会有这样的疑惑->我直接用在函数体里面用if……else不也可以达到这样的效果吗...2.2 虚函数的重写 虚函数:即被virtual修饰的类成员函数称为虚函数 虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同...纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。 在生活中一个类型在现实中没有对应的实体,我们就可以一个类定义为抽象类!...在C++中,常常通过声明顺序来代表实际顺序,比如说 1、初始化列表的初始化顺序取决于成员变量定义的先后顺序 2、一个子类继承多个父类的时候,内存中先继承的父类的成员变量在前面,后继承的父类的成员变量再后面...静态成员可以是虚函数吗? 答:不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表。 6. 构造函数、拷贝构造可以是虚函数吗?
领取专属 10元无门槛券
手把手带您无忧上云