首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
您找到你想要的搜索结果了吗?
是的
没有找到

派生类虚函数和非虚函数的继承效果

,这里是Animal指针指向,所以他就调用Animal里面的,普通函数是父类为子类提供的“强制实现”,也就是只要是父类指针调用普通函数,那就是父类的普通函数 而虚函数的作用,主要是为了让父类指针可以调用子类的函数...2、纯虚函数:   C++包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。   ...C++的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。   C++的纯虚函数也是一种“运行时多态”。...3、普通函数:   普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数。   普通函数是父类为子类提供的“强制实现”。   ...因此,在继承关系,子类不应该重写父类的普通函数,因为函数的调用至于类对象的字面值有关。 参考链接

000

C++|对象模型|对象模型综述

一个古老的实现方法是,在每一个派生类对象存放一个虚指针而非传统对象模型类对象本身,对虚类的访问通过指针间接实现,以此实现共享。...对于问题二: 编译器使用拷贝操作获得所有嵌套虚类的指针存至派生类,以空间换时间,从而解决了固定存取时间的问题。...在派生类指针赋值给指针时编译器需要调整 Base2 * pbase2 =temp ? temp + sizeof (Base1):0; 目的是防止temp==nullptr时,仍然出现偏移。...而在指针调用派生类重写的虚函数时,则需要反过来调整this指针(由编译器插入或者thunk引入),从而正确指向对应的虚表。...虚拟继承下:在虚继承体系单层时,通过上文提及的虚寻址处理,还是可以正确地调整this指针,然而涉及虚类继承虚类时,并且都支持virtual function和nonstatic data member

63410

C++多态

面向对象的程序设计的三大要素之一就是多态,多态是指类的指针指向不同的派生类,其行为不同。...编译器为每个拥有虚函数的对象准备了一个虚函数表,表存储了虚函数的地址,类对象在头四个字节存储了虚函数表的指针。...,并且在派生类重写了函数showClass,在调用时用分别利用类的指针指向类和派生类的对象来调用这个虚函数,得到的结果自然是不同的,这样构成了多态。...由于虚函数表的虚函数是在编译时就根据对象的不同将对应的函数装入到各自对象的虚函数表,因此,不同的对象所拥有的虚函数表不同,最终根据虚函数表寻址到的虚函数也就不同,这样就构成了多态。...对于虚函数的调用,先后经历了几次间接寻址,比直接调用函数效率低了一些,通过虚函数间接寻址访问的情况只有利用类对象的指针或者引用来访问虚函数时才会出现,利用对象本身调用虚函数时,没有必要进行查表,因为已经明确调用的是自身的成员函数

34420

C++:13---多态和虚函数表

多态的意思为“以一个public类的指针/引用,寻址一个派生类对象”。 “多态”的关键在于通过指针或引用调用一个虚函数时,编译时不确定到底调用的是类还是派生类的函数,运行时才确定。...每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着该虚函数表的指针(可以认为这是由编译器自动添加到构造函数的指令完成的)。...图2:类B对象的存储空间以及虚函数表 多态的函数调用语句被编译成根据指针所指向的(或类引用所引用的)对象存放的虚函数表的地址,在虚函数表查找虚函数地址,并调用虚函数的一系列指令。...假设 pa 的类型是 A*,则 pa->func() 这条语句的执行过程如下: 1) 取出 pa 指针所指位置的前 4 个字节,即对象所属的类的虚函数表的地址(在 64 位编译模式下,由于指针占 8...由以上过程可以看出,只要是通过指针类引用调用虚函数的语句,就一定是多态的,也一定会执行上面的查表过程,哪怕这个虚函数仅在类中有,在派生类没有。

68220

C++ 虚拟继承

1.为什么要引入虚拟继承 虚拟继承是多重继承特有的概念。虚拟类是为解决多重继承而出现的。:类D继承自类B1、B2,而类B1、B2都继 承自类A,因此在类D两次出现类A的变量和函数。...虚继承的特点是,在任何派生类的virtual类总用同一个(共享)对象表示,正是如上图所示。...2.1时间:在通过继承类对象访问虚类对象的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚类对象,只不过这个调整是运行时间接完成的...虚拟继承与普通继承不同的是,虚拟继承可以防止出现diamond继承时,一个派生类同时出现了两个类的子对象。也就是说,为了保证 这一点,在虚拟继承情况下,类子对象的布局是不同于普通继承的。...因此,它需要多出一个指向类子对象的指针

2.2K80

CC++面试常问题集(2)

7、类的析构函数为什么要用virtual虚析构函数? C++类采用virtual虚析构函数是为了防止内存泄漏 具体地说,如果派生类申请了内存空间,并在其析构函数对这些内存空间进行释放。...假设采用的是非虚析构函数,当删除指针指向的派生类对象时就不会触发动态绑定,因而只会调用类的析构函数,而不会调用派生类的析构函数。...那么在这种情况下,派生类申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++类的析构函数应采用virtual虚析构函数。...核心理念就是通过类访问派生类定义的函数。它提供了一种接口界面。允许在派生类类的虚函数重新定义。由多态方式调用的时候动态绑定。...(3)指针常量本身(以p为例)允许寻址,即&p返回指针常量(常变量)本身的地址,被引用对象用*p表示;引用变量本身(以r为例)不允许寻址,&r返回的是被引用对象的地址,而不是变量r的地址(r的地址由编译器掌握

1.1K10

【c++】继承学习(一):继承机制与派生类转换

,实际扩展维护性不强 2.类和派生类对象赋值转换 派生类对象可以赋值给类的对象 / 类的指针 / 类的引用。...无法访问,因为_No是Student特有的成员,即使它实际上存在于sobj 即使我们通过类引用或指针操作对象,派生类对象的完整信息(所有成员变量和函数)仍然都在内存,没有丢失。...使用引用和指针时不会发生切片 对象切片的问题仅在派生类对象被赋值给另一个类类型的对象时才会发生,比如当派生类对象被传值给一个类对象的函数参数,或者通过赋值构造一个新的类对象。...在使用引用或指针时,这种情况并不会发生 类对象不能赋值给派生类对象 类的指针或者引用可以通过强制类型转换赋值给派生类指针或者引用。但是必须是类的指针是指向派生类对象时才是安全的。...; } protected: int _num = 999; // 学号 }; void Test() { Student s1; s1.Print(); }; 这段代码展示了成员隐藏,以及如何在派生类访问类的被隐藏成员的概念

28810

C++虚函数表深入探索(详细全面)

,它应该是含有三个指针,分别指向类的虚函数a和类的虚函数c和自己的虚函数b(因为类和派生类中含有同名函数,被覆盖),那么我们就用下面的方式来验证一下: Derive* p = new Derive...可见的三个指针分别指向a,b,c虚函数,而派生类的三个指针第一个和第三个和的相同,那么这就印证了上述我们所假设的情况,那么这也就是虚函数表。...我们来分析这两个类的虚函数表,对于类的虚函数表其实和上面所说的虚函数表是一样的,有自己的虚函数指针,并指向自己的虚函数表,重点是在于派生类的虚函数表是什么样子的,它的样子如下图所示: ?        ...每一个类都会有自己的虚函数表,派生类的虚函数表的数量根据继承的类的数量来定。 2. 派生类的虚函数表的顺序,和继承时的顺序相同。 3....派生类自己的虚函数放在第一个虚函数表的后面,顺序也是和定义时顺序相同。 4. 对于派生类如果要覆盖父类的虚函数,那么会在虚函数表中代替其位置。

17.3K168

深入探索虚函数表(详细)

,它应该是含有三个指针,分别指向类的虚函数a和类的虚函数c和自己的虚函数b(因为类和派生类中含有同名函数,被覆盖),那么我们就用下面的方式来验证一下: Derive* p = new Derive...a,b,c虚函数,而派生类的三个指针第一个和第三个和的相同,那么这就印证了上述我们所假设的情况,那么这也就是虚函数表。...我们来分析这两个类的虚函数表,对于类的虚函数表其实和上面所说的虚函数表是一样的,有自己的虚函数指针,并指向自己的虚函数表,重点是在于派生类的虚函数表是什么样子的,它的样子如下图所示:        ...每一个类都会有自己的虚函数表,派生类的虚函数表的数量根据继承的类的数量来定。 2. 派生类的虚函数表的顺序,和继承时的顺序相同。 3....派生类自己的虚函数放在第一个虚函数表的后面,顺序也是和定义时顺序相同。 4. 对于派生类如果要覆盖父类的虚函数,那么会在虚函数表中代替其位置。

54400

CC++面试题之语言基础篇(一)

继承的三个修饰符: public:公有继承,派生类继承类的公有成员,这些成员在派生类仍然是公有的。...protected:保护继承,派生类继承类的保护成员,这些成员在派生类变为保护或私有的。...private:私有继承,派生类继承类的私有成员,这些成员在派生类变为私有的,不能被外部访问。 C语言和C++的区别 与C语言区别: C语言是面对过程的,而C++是面对对象的。...注意:当数据成员中有指针时,必须要用深拷贝 左值引用和右值引用区别和目的 左值是能够出现在表达式左边的值变量,右值是只能出现在等号右边的值,如常量。 左值可以取地址,右值不可。...结构体的比较,怎么判断两个对象是否相等 需要逐个比较它们的成员变量(字段) 继承关系的子类能访问父类哪些成员变量以及成员函数 在继承关系,子类(派生类)通常可以访问父类(类)的以下成员变量和成员函数

19010

C++继承分析

由于父类的成员在内存的分步是先于派生类自身的成员,所以通过派生类指针可以很容易寻址到父类的成员,而且可以将派生类指针转化为父类进行操作,并且不会出错,但是反过来将父类的指针转化为派生类来使用则会造成越界访问...下面我们来看一下对于虚表指针的初始化问题,如果在存在虚函数,而且在派生类重写这个虚函数的话,编译器会如何初始化虚表指针。...当类的构造函数调用完成后,接着执行派生类的虚表指针的初始化,将它自身虚函数的地址存入到虚表。...通过上面的分析可以知道,在派生类如果重写了的虚函数,那么在创建新的类对象时会有两次虚表指针的初始化操作,第一次是将类的虚表指针赋值给对象,然后再将自身的虚表指针赋值给对象,将前一次的覆盖,如果是在类的构造调用虚函数...,这个时候由于还没有生成派生类,所以会直接寻址,找到的虚函数,这个时候不会构成多态,但是如果在派生类的构造函数调用,这个时候已经初始化了虚表指针,会进行虚表的间接寻址调用派生类的虚函数构成多态。

50730

EasyC++84,私有继承(二)

访问类方法 我们知道,在私有继承时,类的公有对象以及保护对象会变成派生类的私有对象。我们可以在派生类方法当中使用它,但无法通过派生类对象直接调用,但无法访问类的私有方法和对象。...这个概念我们很好理解,但具体到实现上,我们如何在派生类的方法当中调用类的公有或者保护方法呢? 比如,在之前的类声明当中我们声明了一个Average方法,用来计算学生考试成绩的平均分。...由于Student类是继承了valarray类,而非包含一个valarray的实例,那么我们如何在Average方法的实现当中调用valarray的公有方法呢? 答案是通过解析运算符和类名调用。...访问类的友元 方法和对象都好办,但友元怎么办呢?因为友元函数并不属于类,所以无法通过类名或者解析运算符搞定。针对这种情况,我们只能取巧,通过显式地对派生类进行类型转换实现。...引用不会自动发生转换,是因为在私有继承当中,在不进行显式类型转换的情况下,不能将派生类的引用或指针赋给类的引用或指针。 那么问题来了,如果我们使用的是公有继承,那么是不是就可以了呢?

36610

C++ 面试必备:常见 C++ 面试题汇总及详细解析

对于C++程序员来说,精通指针的使用是非常重要的。 重写和重载的区别 重写指的是在派生类重新定义类的虚函数的行为。...当的某个虚函数在派生类中被重新定义时,如果派生类对象调用该函数,则会覆盖掉的实现,执行派生类的实现代码。在进行对象的多态性转换时,重写非常重要。...例如,C++ 可以重载函数来处理不同类型的数据,整数、浮点数等。在使用函数时,根据传递给函数的参数类型和个数来自动选择对应的函数进行调用。...C++类的析构函数声明为虚函数是为了确保在通过类的指针或引用删除派生类对象时,可以正确地释放派生类对象所占用的内存。...如果类的析构函数不是虚函数,则在这种情况下只会调用类的析构函数,而不会调用派生类的析构函数,从而可能导致内存泄漏和未定义行为。

1.8K30

深入探索虚函数表(详细)

,它应该是含有三个指针,分别指向类的虚函数a和类的虚函数c和自己的虚函数b(因为类和派生类中含有同名函数,被覆盖),那么我们就用下面的方式来验证一下: Derive* p = new Derive...a,b,c虚函数,而派生类的三个指针第一个和第三个和的相同,那么这就印证了上述我们所假设的情况,那么这也就是虚函数表。...我们来分析这两个类的虚函数表,对于类的虚函数表其实和上面所说的虚函数表是一样的,有自己的虚函数指针,并指向自己的虚函数表,重点是在于派生类的虚函数表是什么样子的,它的样子如下图所示: image.png...每一个类都会有自己的虚函数表,派生类的虚函数表的数量根据继承的类的数量来定。 2. 派生类的虚函数表的顺序,和继承时的顺序相同。 3....派生类自己的虚函数放在第一个虚函数表的后面,顺序也是和定义时顺序相同。 4. 对于派生类如果要覆盖父类的虚函数,那么会在虚函数表中代替其位置。

1.1K80

C++多态

一个含有虚函数的类至少都有一个虚函数表指针,且有一个虚表,虚函数指针指向虚函数表。虚表可以继承,如果子类没有重写虚函数,那么子类虚表仍然会有该函数的地址,只不过这个地址指向的是类的虚函数实现。...如果派生类有自己的虚函数,那么虚表中就会添加该项。派生类的虚表虚函数地址的排列顺序和类的虚表虚函数地址排列顺序相同。...虚函数的作用主要是实现了多态的机制,类定义虚函数,子类可以重写该函数;在派生类类定义的虚函数进行重写时,需要在派生类声明该方法为虚方法,否则将会形成覆盖。...如果的虚方法没有在派生类重写,那么派生类将继承的虚方法,而且派生类虚函数表将保存未被重写的虚函数的地址。...虚函数表指针(vfptr)指向虚函数表(vftbl)的某一项,虚函数表按照对象继承的顺序排列对象的虚函数地址,虚类表按照对象继承的顺序排列对象的直接虚继承类到虚类的偏移。

1.7K10

C++:29 --- C++继承关系下的内存布局(下)

那些特例,鸭嘴兽(生蛋的哺乳动物),则要求我们对缺省的属性或行为进行覆盖。 C++的继承语法很简单,在子类后加上“:base”就可以了。下面的D继承自类C。...观察类布局,可以看到F内嵌的E对象,其指针与F指针并不相同。正如后文讨论强制转化和成员函数时指出的,这个偏移量会造成少量的调用开销。 具体的编译器实现可以自由地选择内嵌类和派生类的布局。...当使用指针访问虚类成员变量时,由于指针可以是指向派生类实例的指针,所以,编译器不能根据声明的指针类型计算偏移,而必须找到另一种间接的方法,从派生类指针计算虚类的位置。...该变量指向一个全类共享的偏移量表,表项目记录了对于该类 而言,“虚类表指针”与虚类之间的偏移量。 其它的实现方式,有一种是在派生类中使用指针成员变量。...(在G,虚类对象C的地址与G的“虚类表指针”之间的偏移量 ( 当对于所有的派生类来说偏移量不变时,省略“d”前的前缀))。比如,在32位平台上,GdGvptrC是8个字节。

1.2K20
领券