本文将深入解析虚函数与纯虚函数的区别,并通过实例展示它们在实际编程中的应用。一、虚函数虚函数是指在C++中,被virtual关键字修饰的成员函数。...如果子类没有覆盖基类的虚函数,那么当通过基类指针或引用调用该函数时,将调用基类的虚函数实现。二、纯虚函数纯虚函数是一种特殊的虚函数,它在声明时除了加上virtual关键字外,还需要加上=0。...由于纯虚函数没有实现,因此它所在的类被称为抽象类。抽象类不能实例化对象,只能作为基类为派生类服务。派生类必须实现基类中所有的纯虚函数,否则派生类也将成为抽象类,不能实例化对象。...// Shape shape; // 实例化派生类 Circle circle; // 调用派生类实现的纯虚函数 circle.draw(); // 调用基类中的虚函数实现...通过实例化Circle类对象并调用其成员函数,可以看到虚函数和纯虚函数在实际编程中的应用效果。
; 纯虚函数(pure virtual) C++中包含纯虚函数的类,被称为是“抽象类”。...抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。 C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。 ...C++中的纯虚函数也是一种“运行时多态”。 ...} //派生类中可以不写这个函数,但是派生类对象调用时会调用积累的虚函数 //纯虚函数 virtual void cxhs() =0; //这个纯虚函数不在基类中实现,必须在子类中实现...c.cxhs();//调用派生类的 }
C++的虚函数是一种特殊的成员函数,用于实现多态性。虚函数允许在基类中声明一个函数,在派生类中根据需要进行重写,并通过基类指针或引用来调用派生类对象的特定实现。...通过将基类指针ptr指向派生类对象derivedObj,我们可以通过调用虚函数show()来实现多态性。运行时会根据实际对象的类型选择正确的实现。...Base* ptr; // 基类指针 Derived derivedObj; // 派生类对象 ptr = &derivedObj; // 将基类指针指向派生类对象 // 调用虚函数,根据对象的实际类型执行不同的实现...ptr->show(); ③派生类重写虚函数 派生类可以重写基类中的虚函数,以提供自己的实现。...纯虚函数通过在声明中使用= 0来标识。包含纯虚函数的类称为抽象类,它不能实例化,只能作为基类来派生其他类。
1 /*曾经有段时间一直被构造函数中的虚函数所困扰,现在通过自己重新学习了一遍,标注一下容易忘记的知识*/ 2 #include 3 using namespace std;...4 class Base0 5 { 6 public: 7 Base0(int var):var0(var) 8 { 9 coutbase0...15 } 16 17 }; 18 class Base1 :virtual public Base0 19 { 20 public: 21 Base1(int var) :Base0...Base2 : virtual public Base0 28 { 29 public : 30 Base2(int var): Base0(var) 31 { 32...Base1 //构造函数的执行顺序与这儿有关 37 { 38 public : 39 Derived(int var) : Base2(var),Base1(var),Base0(var
当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。 C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。...虚函数: 虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。...我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。...纯虚函数:(java中抽象函数) 您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数() 例子: 1.虚函数...而c++中的纯虚函数是可以有方法体,也就是说是可以给出定义的,并且,在c++中,子类还可以调用父类的纯虚函数
base3,因为eye是个普通函数,在编译阶段就确定好是被谁调用,所以他只认哪个指针指向自己,这里是Animal指针指向,所以他就调用Animal里面的,普通函数是父类为子类提供的“强制实现”,也就是只要是父类指针调用普通函数...,那就是父类的普通函数 而虚函数的作用,主要是为了让父类指针可以调用子类的函数,这种是在运行时才决定调用哪个函数 1、虚函数: C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现...子类可以重写父类的虚函数实现子类的特殊化。 2、纯虚函数: C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。 ...C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。 C++中的纯虚函数也是一种“运行时多态”。...因此,在继承关系中,子类不应该重写父类的普通函数,因为函数的调用至于类对象的字面值有关。 参考链接
; } }; 2.纯虚函数(pure virtual) C++中包含纯虚函数的类,被称为是“抽象类”。...抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。 C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。 ...C++中的纯虚函数也是一种“运行时多态”。 ...“字面值”类对象,调用自己的普通函数。 ...普通函数是父类为子类提供的“强制实现”。 因此,在继承关系中,子类不应该重写父类的普通函数,因为函数的调用至于类对象的字面值有关。
例如: Base baseObj; baseObj.Func(); // 这样的调用会导致编译错误,因为Base类中Func是纯虚函数,无函数体 派生类要求 纯虚函数必须在派生类中进行定义,否则该虚函数在派生类中依然保持为纯虚函数状态...当派生类实现了这个纯虚函数后,才能通过派生类的对象调用这个函数,且调用时执行的是派生类中定义的函数逻辑。...基类定义了一系列纯虚函数作为接口,不同的派生类根据自身的特点和需求去具体实现这些函数,这样就可以通过基类指针或引用指向不同的派生类对象,并调用这些虚函数时,执行不同派生类中对应的函数实现,呈现出多态的行为...通过基类 Shape 的指针指向不同派生类对象,调用 draw 函数时,根据对象实际类型执行相应派生类中定义的绘制逻辑,体现了多态性。...四、注意事项 继承关系中的纯虚函数处理 在多层继承结构中,如果中间层派生类没有对基类的纯虚函数进行定义,那么这个纯虚函数依然会传递下去,在该中间层派生类的派生类中依然需要进行定义才能实例化对象。
这使得在继承关系中,通过基类指针或引用调用虚函数时,可以根据实际对象的类型来动态地确定要执行的函数版本,实现多态性的特性。...在C++中,当基类的指针或引用指向派生类的对象时,通过调用虚函数,可以实现对应于派生类的特定实现。这种根据对象的实际类型来确定调用哪个函数的机制就是动态绑定。...纯虚函数(Pure Virtual Function)是在基类中声明的没有实际实现的虚函数。它通过在函数声明后面加上= 0来表示。 纯虚函数在基类中起到了接口的定义作用,要求派生类必须提供对应的实现。...->pureVirtualFunction(); // 通过基类指针调用Derived类的实现 return 0; } 在上述示例中,Base类中的pureVirtualFunction函数被声明为纯虚函数...Derived类继承自Base类,并提供了对纯虚函数的具体实现。通过Derived类的对象或基类指针可以调用纯虚函数的具体实现。 纯虚函数允许在基类中定义一组接口,并强制要求派生类提供相应的实现。
如果定义为虚函数,那么它就是动态绑定的,也就是在派生类中可以被覆盖的,这与静态成员函数的定义(在内存中只有一份拷贝,通过类名或对象引用访问静态成员)本身就是相矛盾的。...如果不定义虚析构函数,当删除一个指向派生类对象的指针时,会调用基类的析构函数,派生类的析构函数未被调用,造成内存泄露。...虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。这样,当删除指向派生类的指针时,就会首先调用派生类的析构函数,不会有内存泄露的问题了。...在有虚函数类的实例中,分配了指向这个表的指针的内存,所以,当用父类的指针来操作一个子类对象实体的时候,这张虚函数表就指明了实际所应该被调用的虚函数。...实现了基类Base类的虚函数和纯虚函数,同时注意到,企图去实例化抽象类,编译器会报错。
当通过基类指针删除派生类对象时,如果基类的析构函数不是虚的,那么只会调用基类的析构函数,而不会调用派生类的析构函数。...: 虚函数允许在派生类中重写基类的成员函数,并通过基类指针或引用来调用派生类的函数实现,从而实现多态。...由于至少含有一个纯虚函数,抽象类不能被实例化(即不能直接创建该类的对象)。抽象类的主要用途是作为一个基类,为派生类提供一个公共的接口。...总结 纯虚函数和抽象类是面向对象编程中用于实现接口和多态性的重要工具。纯虚函数要求派生类必须提供实现,而抽象类则是因为包含至少一个纯虚函数而不能被直接实例化。...通过基类类型的指针或引用来调用虚函数时,会根据实际的对象类型来调用相应的函数。 抽象类:定义一个只包含纯虚函数的类作为抽象基类,派生类必须实现这些纯虚函数才能被实例化。
多态是一种非常强大的机制,我们考虑这种情况,基类早已写好并定义了良好的接口,基类的使用者编写代码时,将能通过基类的接口来调用派生类中的方法,也就是说,后写的代码能被先写的代码调用,这使程序具有很强的复用性和扩展性...换句话说,对于使用 new 在堆内存中实例化的派生类对象,如果将其赋给基类指针,并通过基类指针调用 delete,如果基类析构函数不是虚函数,delete 将按基类析构的方式来析构此指针,如果基类析构函数是虚函数...实例,但该实例的 VFT 指针仍指向 Derived 类的虚函数表,因此通过该 VTF 执行的是 Derived::Func1()。...纯虚函数和抽象基类 在 C++ 中,包含纯虚函数的类是抽象基类。抽象基类用于定义接口,在派生类中实现接口,这样可以实现接口与实现的分离。抽象基类不能被实例化。...B::func3 B::func4 B::func5 结论如下: 类中只要有一个纯虚函数,这个类就是抽象基类,不能被实例化 基类中的纯虚函数,基类不能给出实现,必须在派生类中实现,即一定要有派生类中覆盖基类的纯虚函数
根据引用或指针所绑定的对象类型不同,该调用可能执行基类的版本,也可能执行某个派生类的版木,基类通过在其成员函数的声明语句之前加上关键字virtual使得该函数执行动态绑定。...成员函数如果没被声明为虚函数,则其解析过程发生在编译时而非运行时。就会按照实际情况调用。 派生类可以继承定义在基类中的成员,但是派生类的成员函数不一定有权访问从基类继承而来的成员。...1.虚析构与纯虚析构共性: 解决父类指针释放子类对象不干净问题 都需要有具体的函数实现 2.区别: 如果是纯虚析构,该类属于抽象类,无法实例化 .虚析构语法: virtual ~类名(){}...纯虚析构语法: virtual ~类名()=0; 类名::~类名(){} 纯虚数 子类的内容会覆盖父类,所以父类中函数没有意义了 类中只要有一个纯虚函数就称为抽象类 virtual void...抽象类无法实例化对象(堆区,栈区) 子类也必须要重写父类中的虚函数,否则子类也就是抽象类 */ virtual ~base() { cout base的析构函数" << endl;
继承中要构成多态还有两个条件: 必须通过基类的指针或者引用调用虚函数 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写 如果是通过基类的指针调用虚函数,要如下图所示使用: 虚函数 虚函数...重载、覆盖(重写)、隐藏(重定义)的对比 抽象类 概念 在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口 类),抽象类不能实例化出对象。...派生类继承后也不能实例化出对象,只有重写纯虚函数,派生 类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。 Benz没有重写纯虚函数,所以不能实例化对象。...派生类的虚表生成:1.先将基类中的虚表内容拷贝一份到派生类虚表中 2.如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数 3.派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后...基类引用引用子类对象后,通过基类对象调用f2时,调用的是子类的f2(错) 解释:通过对象调用时编译期间就直接确定调用那个函数了,不会通过虚表以多态方式调用 3 虽然进行了强转,pa指向的依旧是是B
: 虚函数是在基类中声明的,并在派生类中重写的函数。...通过在函数声明前加上virtual关键字来声明虚函数。虚函数是实现动态多态的关键,因为它允许在运行时根据对象的实际类型来调用相应的函数。...2、通过基类指针或引用调用虚函数: 多态通常通过基类的指针或引用来实现。当使用基类指针或引用指向派生类对象时,调用虚函数将根据对象的实际类型(而不是指针或引用的类型)来决定调用哪个函数。...这是因为当通过基类指针删除派生类对象时,如果析构函数不是虚函数,将只会调用基类的析构函数,而不会调用派生类的析构函数,这可能导致资源泄漏。...抽象类只有在将其中的纯虚函数重写之后才能实例化对象。抽象类主要用于定义接口,实际的业务逻辑通常由继承它的具体子类来实现。
那么在继承中要构成多态还有两个条件: 必须通过基类的指针或者引用调用虚函数 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写 1....概念 在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。...派生类继承后也不能实例化出派生类对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。 2....b; Derive d; return 0; } 从监视窗口可得到这些信息: 基类与派生类的虚表不一样 基类的虚表中存储的是基类的虚函数Base::Fun1,Base::Fun2 派生类的虚表中存储的是...虚函数覆盖:派生类中重写的虚函数会覆盖派生类对象虚表中的基类继承的函数指针,未重写的基类的虚函数依次存储在该派生类对象的虚表中,这样派生类对象的虚表中就同时存在基类与派生类的函数指针,在用基类对象指针或引用调用的时候通过
调用 Base 类的 show() 纯虚函数和抽象类 纯虚函数(Pure Virtual Function) 在C++中,虚函数后加= 0,就将该函数声明为纯虚函数。...class Car { public: virtual void Drive() = 0; // 纯虚函数 }; Car类不能直接实例化,因为它包含了纯虚函数,必须由派生类来实现。...抽象类(Abstract Class) 抽象类是指包含一个或多个纯虚函数的类。抽象类不能被实例化,必须通过派生类进行实例化。...抽象类的作用是为派生类提供统一的接口,使得多个派生类可以通过相同的接口进行调用,从而实现多态。 特点:抽象类不能被直接实例化,它只能作为基类存在。...派生类要求:派生类必须实现抽象类中的所有纯虚函数,否则派生类也将成为抽象类,无法实例化。
运行时多态: 通过虚函数和继承实现,是在运行阶段确定函数调用。运行时多态允许通过基类指针或引用来调用派生类的函数,实现了动态绑定。...通过基类指针或引用调用虚函数时,将根据对象的实际类型调用相应的派生类函数 从上面这段话我们知道在继承中要构成多态还有两个条件: 必须通过基类的指针或者引用调用虚函数 被调用的函数必须是虚函数...包含纯虚函数的类叫做抽象类 (也叫接口 类),抽象类不能实例化出对象,但可以定义基类指针,用来实现多态 派生类继承后也不能实例化出对象, 只有重写纯虚函数,派生类才能实例化出对象 。...纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承 class Car//抽象类,不能实例化出对象 { public: virtual void Drive() = 0; // 纯虚函数...因此,基类对象中的虚函数调用会绑定到基类的虚函数表上,而无法访问派生类的虚函数。
动态绑定:在main函数中,通过基类引用和指针来调用派生类的sound方法,输出的是实际派生类的结果。...2.4.2 使用虚析构函数 通过将基类的析构函数声明为虚函数,可以确保正确调用派生类的析构函数,避免内存泄漏问题: #include class Base { public:...() {} // 提供析构函数体 总结 虚析构函数确保通过基类指针删除派生类对象时正确调用派生类的析构函数,避免内存泄漏。...3.1 抽象类的定义 抽象类的定义中包含纯虚函数,纯虚函数的声明形式为: virtual 返回类型 函数名(参数列表) = 0; 这个 = 0 表示该函数是纯虚函数,必须在派生类(子类)中实现。...3.2 抽象类的特点: 不能直接实例化抽象类对象。例如 Shape 不能直接创建对象。 抽象类中的纯虚函数必须在派生类中实现,否则派生类也会变成抽象类。
二.多态的定义和实现 2.1多态的构成条件 派生类对基类的虚函数实现重写 通过基类的指针或引用调用虚函数 虚函数是什么呢?...在讲抽象类之前先讲讲纯虚函数,我们在虚函数的后面加上=0,这样的虚函数就叫纯虚函数。...class Car { public: virtual void Drive() = 0; }; 3.2概念 包含纯虚函数的类就是我们的抽象类了,抽象类是不能实例化出对象的,而且他的派生类也不能,只有派生类重写了纯虚函数...当p指向Mike对象时,p->BuyTicket()在虚表中调用的是Person::BuyTicket() 而当p指向Johnson对象时,p->BuyTicket()在虚表中调用的是Student::...通过对汇编代码的分析发现,满足多态的函数调用,是在运行后到对象中去找的,而不满足多态的函数调用,是在编译时就确认好的。
领取专属 10元无门槛券
手把手带您无忧上云