-
3-8 基类指针、虚函数 override、final 、虚纯虚函数、多态性、虚析构
2019-04-28 13:18:41基类指针、虚函数、多态性、纯虚函数、虚析构 虚函数:https://blog.csdn.net/samkieth/article/details/49737757 C++为什么要用虚函数:https://blog.csdn.net/noricky/article/details/...3-8 基类指针、虚纯虚函数、多态性、虚析构
虚函数:https://blog.csdn.net/samkieth/article/details/49737757
C++为什么要用虚函数:https://blog.csdn.net/noricky/article/details/80051219
一、基类指针、派生类指针
父类指针可以new一个子类对象
//Human.h class Human{ public: Human(); void eat(); }; //Human.cpp Human::Human(){ cout << "父类Human" << endl; } Human::eat(){ cout << "父类eat" << endl; } //--------------------------------------------------------------------- //Man.h class Man: public Human{ public: Man(); void eat(); }; //Man.cpp Man::Man(){ cout << "子类Man" << endl; } void Man::eat(){ cout << "Man:eat" << endl; } int main(){ Human *phuman = new Man(); phuman -> eat(); //调用了父类Human的eat函数。因为phuman 父类指针。 }
Human *phuman = new Man; //父类的指针指向了一个new出来的子类对象。 phuman->func_human(); //父类指针可以调用父类的成员函数。 phuman->func_man(); //不可以,虽然new子类对象,但是父类指针无法调用子类的成员函数。
既然父类指针没办法调用子类成员函数,那么为什么要让父类指针可以指向子类对象?其实我们可以通过一些方法调用父类及各个子类的函数。
如果我们想要通过一个父类指针调用父类、子类中的同名同参函数的化,那么对这个函数是有要求的:在父类中必须在声明这个函数时在函数之前加 virtual ,声明成虚函数(建议在子类中也加上virtual,方便阅读)。
二、虚函数
//Human.h class Human{ public: Human(); virtual void eat(); }; //Human.cpp Human::Human(){ cout << "父类Human" << endl; } void Human::eat(){ cout << "父类eat" << endl; } //--------------------------------------------------------------------- //Man.h class Man: public Human{ public: Man(); virtual void eat(); }; //Man.cpp Man::Man(){ cout << "子类Man" << endl; } void Man::eat(){ cout << "Man:eat" << endl; } //---------------------------------------------------------------------- //Woman.h class Woman: public Human{ public: Woman(); virtual void eat() override; }; //Woman.cpp Woman::Woman(){ cout << "子类Woman" << endl; } void Woman::eat(){ cout << "Woman:eat" << endl; } int main(){ Human *phuman = new Man(); phuman->eat(); //调用的时Man中的eat函数 phuman->Human::eat(); //通过这种方式可以调用父类中的eat函数 delete phuman; Human *phuman = new Woman(); phuman->eat(); //调用的时Woman中的eat函数 delete phuman; Human *phuman = new Human(); phuman->eat(); //调用的时Human中的eat函数 delete phuman; }
有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数?
有解决方案,这个对象指针必须是一个父类类型,我们如果想通过一个父类指针调用父类、子类中的同名函数的话,这个函数是有要求的;
在父类中,eat函数声明之前必须要加virtual声明eat()函数为虚函数。
一旦某个函数被声明为虚函数,那么所有派生类(子类)中eat()函数都是虚函数。
为了避免你在子类中写错虚函数,在C++11中,你可以在函数声明中增加一个override关键字,这个关键字用在子类中,而且是虚函数专用。
override就是用来说明派生类中的虚函数,你用了这个关键字之后,编译器就会认为你这个eat是覆盖了父类中的同名函数(只有虚函数才存在子类可以覆盖父类中同名函数的问题),那么编译器就会在父类中找同名的虚函数,如果没找到,编译器就会报错,如果你不小心在子类中把虚函数写错了名字,写错了参数,编译器能够帮你进行纠错。
final也是虚函数专用,用在父类中,如果我们在父类的函数声明中加了final,那么任何尝试覆盖在函数的操作都会引发错误。
调用虚函数执行的是“动态绑定”。动态表示我们程序运行的时候才能知道调用了那个子类的中的eat()虚函数。
动态的绑定到Men上去,还是Women上去,取决于new的Men还是Women;
动态绑定:运行的时候才决定你的phuman对象绑定到那个eat()函数上运行。
三、多态性
多态性只是针对虚函数来说的;
多态性:体现在具有继承关系的父类和子类之间,子类重新定义(重写)父类的成员函数eat(),同时父类把这个eat()函数声明为virtual虚函数;
通过父类的指针,只有到了程序运行时期,找到动态绑定到父类指针上的对象,这个对象有可能是某个子类对象,也可能是父类对象;
然后系统内部实际上是要查找一个虚函数表,找到函数eat()的入口地址,从而调用父类或子类的eat()函数,这就是运行时的多态性。
四、纯虚函数
纯虚函数是在基类中声明的函数,但是他在基类中没有定义,但是要求任何派生类都要定义该虚函数自己的实现方法;
基类中实现纯虚函数的方法使在函数原型后面增加 =0;
//Human.h class Human{ public: Human(); virtual void eat() =0; //定义纯虚函数 }; //Human.cpp Human::Human(){ cout << "父类Human" << endl; }
一旦一个类中有纯虚函数,那么你就不能生成这个类的对象了;
抽象类不能用来生成对象,主要目的是用来同意管理子类对象;
(1)纯虚函数的类叫做抽象类,不能用来生成该类对象,主要用于当做基类来生成子类用的;
(2)子类必须要实现该基类中定义纯虚函数;
五、基类的析构函数一般写成虚函数(虚析构函数)
//Human.h class Human{ public: Human(); ~Human(); }; //Human.cpp Human::Human(){ cout << "父类Human" << endl; } Human::~Human(){ cout << "父类~Human()" << endl; } //--------------------------------------------------------------------- //Man.h class Man: public Human{ public: Man(); ~Man(); void say(); }; //Man.cpp Man::Man(){ cout << "子类Man" << endl; } ~Man(){ cout << "子类~Man()" << endl; } void Man::say(){ cout << "say()" << endl; } //-------------------------------------------------------------------- int main(){ Man *pman = new Man(); //调用 Human() Man() delete pman; //调用 ~Man() ~Human() Human *phuman = new Man(); //调用 Human() Man() delete phuman; //只调用了 ~Human() phuman->say(); //报错,因为基类中没有say(),基类指针无法指向子类中基类没有的成员函数 }
用基类指针new子类的对象,在delete的时候,系统不会调用派生类的析构函数,存在问题;
解决方案:将基类的析构函数声明为虚析构函数;
在public继承中,基类对派生类及其对象的操作,只能影响那些从基类继承下来的成员,如果想要用基类对非继承的成员进行操作,则要把基类的这个函数定义为虚函数,析构函数也为虚函数,基类中的析构函数的虚属性也会被派生类继承,即派生类的析构函数也为虚函数。
Human这个类中的析构函数就要声明为virtual的,也就是说C++11中为了获得运行时多态,所调用的成员必须是virtual的。
如果一个类想要做基类,我们必须将类的析构函数声明为virtual虚函数;
只要基类中的析构函数为虚函数,就能保证我们delete基类指针时能够运行正确,不会出现内存泄漏。
虚函数会增加内存开销,类里面定义虚函数,编译器就会给这个类增加虚函数表,在这个表里存放虚函数的指针。
本节案例:
// Human.h // 头文件防卫式声明 #ifndef __HUMAN__ #define __HUMAN__ #include "stdafx.h" class Human { public: Human(); virtual ~Human(); public: virtual void eat(); virtual void eat2() = 0; }; #endif // Human.cpp #include "stdafx.h" #include "Human.h" #include <iostream> Human::Human() { std::cout << "调用了Human::Human()" << std::endl; } void Human::eat() { std::cout << "人类喜欢吃各种美食" << std::endl; } Human::~Human() { std::cout << "调用了Human::~Human()" << std::endl; } // Men.h #ifndef __MEN__ #define __MEN__ #include "stdafx.h" #include "Human.h" class Men : public Human { public: Men(); ~Men(); public: virtual void eat() override; virtual void eat2(); }; #endif // Men.cpp #include "stdafx.h" #include "Men.h" #include <iostream> void Men::eat() { std::cout << "男人喜欢吃米饭" << std::endl; } void Men::eat2() { std::cout << "男人喜欢吃米饭2" << std::endl; } Men::Men() { std::cout << "调用了Men::Men()" << std::endl; } Men::~Men() { std::cout << "调用了Men::~Men()" << std::endl; } // Women.h #ifndef __WOMEN__ #define __WOMEN__ #include "stdafx.h" #include "Human.h" class Women : public Human { public: Women(); ~Women(); public: virtual void eat() override; virtual void eat2() override; }; #endif // Women.cpp #include "stdafx.h" #include "Women.h" #include <iostream> Women::Women() { std::cout << "调用了Women::Women()" << std::endl; } Women::~Women() { std::cout << "调用了Women::~Women()" << std::endl; } void Women::eat() { std::cout << "女人喜欢吃面食" << std::endl; } void Women::eat2() { std::cout << "女人喜欢吃面食2" << std::endl; } // main.cpp // Project3.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include "Human.h" #include "Men.h" #include "Women.h" using namespace std; int main() { Human *phuman = new Men; phuman->eat(); // 男人喜欢吃米饭 delete phuman; phuman = new Women; phuman->eat(); // 女人喜欢吃面食 delete phuman; //phuman = new Human; //phuman->eat(); // 人类喜欢吃各种美食 //delete phuman; phuman = new Men; phuman->eat2(); // 男人喜欢吃米饭 delete phuman; phuman = new Women; phuman->eat2(); // 女人喜欢吃面食 delete phuman; //Men men; Men *pmen = new Men; delete pmen; Human *phuman1 = new Men; delete phuman1; // 没有执行子类的析构函数 return 0; }
-
C++新特性 虚函数override及类的final等
2021-02-26 22:18:41待补充待补充
//虚函数 override final default delete 在C++11新增 struct Base { public: virtual void foo() final {};//标注final }; //子类继承父类函数重载 class SubClass final :public Base { public: // override显示的告诉这个是虚函数,在后期维护的时候可以方便看到,用于提醒 void foo() override{};//b报错 }; // final 如果在类后面标注告诉编译器,这是最后一个类,无法在被继承的类 //final 在虚函数后面,告诉派生类无法在重载这个类的虚函数了 class subclass2 :public SubClass //报错 { public: }; //default class Base01 { public: Base01() = default;//保留默认构造析构拷贝函数 Base01(int i) //如何没有default 则默认没有无参构造 { } }; //delete class Base02 { public: Base02() = delete;//禁止编译器参数默认构造 Base02(int i) { } }; int main() { return 0; }
-
基类指针,子类指针,虚函数,override与final
2020-10-19 23:47:58一:基类指针与子类指针 在这里插入代码片 二:虚函数 ...c++11引入的override与final关键字在虚函数中的应用。 说明:override只能在子类中使用,而final只能在父类中使用,并且是只能用在虚函数上。 ...一:基类指针与子类指针
#include "pch.h" #include <iostream> using namespace std; class human { public: void eat() { cout << "各种粮食" << endl; }; }; class man :public human { public: void eat() { cout << "面食" << endl; }; }; class woman :public human { public: void eat() { cout << "米饭" << endl; }; }; int main() { //没问题, human *phuman = new human; //基类指针 man *pman = new man; //子类指针 woman *pwoman = new woman; //子类指针 //新玩法,一个父类指针可以new一个子类对象 human *phuman1 = new man; phuman1->eat();//虽然是new子类对象,但是,这里调用的还是父类中的eat函数。 /* 说明: 1:一个父类指针可以new一个对象,是因为子类中含有的子对象包括父类, 但是,一个子类new一个父类对象就不可以了。 2:我要怎么样用一个父类指针就可以调用子类中的eat函数呢? */ return 0; }
二:虚函数
/*一:抛出了一个问题,即如何用一个父类指针去调用子类里的eat函数?有办法吗?有,那就是引入虚函数,这样就可以用一个父类指针即调用父类的eat函数又可以调用子类的eat函数了*/ #include "pch.h" #include <iostream> using namespace std; class human { public: virtual void eat() { cout << "各种粮食" << endl; }; /* 在函数声明前加上virtual,这个函数就成了虚函数了,注意是声明,不是定义, 要是声明和定义放在一块,也可以加上virtual,就像上面那样。 在类外实现时,不用加virtual */ }; class man :public human { public: void eat() { cout << "面食" << endl; }; }; class woman :public human { public: void eat() { cout << "米饭" << endl; }; }; int main() { human *phuman = new man; phuman->eat(); //这样调用的就是子类的eat函数了 //那我怎么调用父类里的eat函数? human *phuman1 = new man; phuman1->human::eat();//ok,显示调用的父类的eat函数 /* eat函数。如果在类中中加了virtual,那么子类中就不用加上这个关键字了 这样,在调用eat函数的时候,执行的就是动态绑定了,即new什么就调用谁 */ return 0; }
三:override与final关键字
c++11引入的override与final关键字在虚函数中的应用。说明:override只能在子类中使用,而final只能在父类中使用,并且是只能用在虚函数上(或者是用在基类上,用来阻止派生类的继承)。
final与override相对,在父类的虚函数加上它以后,就是说,不要希望在子类中去覆盖父类的eat函数,用了final以后,再用override就不可以了。或者说是用了final以后,子类中就不能在写eat函数了。
#include "pch.h" #include <iostream> using namespace std; class human { public: virtual void eat() { cout << "各种粮食" << endl; }; /* 在函数声明前加上virtual,这个函数就成了虚函数了,注意是声明,不是定义, 要是声明和定义放在一块,也可以加上virtual,就像上面那样。 在类外实现时,不用加virtual */ /* virtual void eat() final; 这样写,后面子类就不能写eat函数了。 */ }; class man :public human { public: void eat() { cout << "面食" << endl; }; }; class woman :public human { public: void eat(int a) override{ cout << "米饭" << endl; }; /*错误,加上override的意思是说,要覆盖父类中的同名同参的虚函数函数,也就是说,为了防止我们写错参数个数或者函数名,那么你加上override以后,编译器就会对你提示错误,比如这里报错的原因就是因为,父类的虚函数中,没有参数为int的eat函数*/ }; int main() { human *phuman = new man; phuman->eat(); //这样调用的就是子类的eat函数了 //那我怎么调用父类里的eat函数? human *phuman1 = new man; phuman1->human::eat();//ok,显示调用的父类的eat函数 /* eat函数。如果在类中中加了virtual,那么子类中就不用加上这个关键字了 这样,在调用eat函数的时候,执行的就是动态绑定了,即new什么就调用谁 */ return 0; }
附:有那些函数不能声明为虚函数:
https://www.cnblogs.com/dingou/p/11627596.html -
c++ 公有继承 虚函数 和 override
2020-10-24 10:51:33公有继承包含两部分:一是 “函数接口” (interface),二是 “函数实现” (implementation) 如 Shape 类中,三个成员函数,对应三种继承方式: class Shape { public: virtual void Draw() const = 0; // 1) 纯虚...转载自
https://www.cnblogs.com/xinxue/p/5471708.html1 公有继承
公有继承包含两部分:一是 “函数接口” (interface),二是 “函数实现” (implementation)如 Shape 类中,三个成员函数,对应三种继承方式:
class Shape { public: virtual void Draw() const = 0; // 1) 纯虚函数 virtual void Error(const string& msg); // 2) 普通虚函数 int ObjectID() const; // 3) 非虚函数 }; class Rectangle: public Shape { ... }; class Ellipse: public Shape { ... };
1.1 纯虚函数 (pure virtual)
纯虚函数,继承的是基类中,成员函数的接口,且要在派生类中,重写成员函数的实现Shape *ps1 = new Rectangle; ps1->Draw(); // calls Rectangle::Draw Shape *ps2 = new Ellipse; ps2->Draw(); // calls Ellipse::Draw
调用基类的 Draw(),须加 类作用域操作符 ::
ps1->Shape::Draw(); // calls Shape::draw
1.2 普通虚函数
普通虚函数,会在基类中,定义一个缺省的实现 (default implementation),表示继承的是基类成员函数接口和缺省实现,由派生类选择是否重写该函数。实际上,允许普通虚函数 同时继承接口和缺省实现是危险的。 如下, ModelA 和 ModelB 是 Airplane 的两种飞机类型,且二者的飞行方式完全相同
class Airplane { public: virtual void Fly(const string& destination); }; class ModelA: public Airplane { ... }; class ModelB: public Airplane { ... };
这是典型的面向对象设计,两个类共享一个特性 – Fly,则 Fly 可在基类中实现,并由两个派生类继承之
现增加另一个飞机型号 ModelC,其飞行方式与 ModelA,ModelB 不相同,如果不小心忘记在 ModelC 中重写新的 Fly 函数
class ModelC: public Airplane { ... // no fly function is declared };
则调用 ModelC 中的 fly 函数,就是调用 Airplane::Fly,但是 ModelC 的飞行方式和缺省的并不相同
Airplane *pa = new ModelC; pa->Fly(Qingdao); // calls Airplane::fly!
即前面所说的,普通虚函数同时继承接口和缺省实现是危险的,最好是基类中实现缺省行为 (behavior),但只有在派生类要求时才提供该缺省行为
1.2.1 方法一
一种方法是 纯虚函数 + 缺省实现,因为是纯虚函数,所以只有接口被继承,其缺省的实现不会被继承。派生类要想使用该缺省的实现,必须显式的调用class Airplane { public: virtual void Fly(const string& destination) = 0; }; void Airplane::Fly(const string& destination) { // a pure virtual function default code for flying an airplane to the given destination } class ModelA: public Airplane { public: virtual void Fly(const string& destination) { Airplane::Fly(destination); } };
这样在派生类 ModelC 中,即使一不小心忘记重写 Fly 函数,也不会调用 Airplane 的缺省实现
class ModelC: public Airplane { public: virtual void Fly(const string& destination); }; void ModelC::Fly(const string& destination) { // code for flying a ModelC airplane to the given destination }
1.2.2 方法二
可以看到,上面问题的关键就在于,一不小心在派生类 ModelC 中忘记重写 fly 函数,C++11 中使用关键字 override,可以避免这样的“一不小心”1.3 非虚函数
非虚成员函数没有 virtual 关键字,表示派生类不但继承了接口,而且继承了一个强制实现 (mandatory implementation)既然继承了一个强制的实现,则在派生类中,无须重新定义 (redefine) 继承自基类的成员函数,如下:
使用指针调用 ObjectID 函数,则都是调用的 Shape::ObjectID()
Rectangel rc; // rc is an object of type Rectangle Shape *pB = &rc; // get pointer to rc pB->ObjectID(); // call ObjectID() through pointer Rectangle *pD = &rc; // get pointer to rc pD->ObjectID(); // call ObjectID() through pointer
如果在派生类中重新定义了继承自基类的成员函数 ObjectID 呢?
class Rectangel : public Shape { public: int ObjectID() const; // hides Shape::ObjectID }; pB->ObjectID(); // calls Shape::ObjectID() pD->ObjectID(); // calls Rectagle::ObjectID()
此时,派生类中重新定义的成员函数会 “隐藏” (hide) 继承自基类的成员函数
这是因为非虚函数是 “静态绑定” 的,pB 被声明的是 Shape* 类型的指针,则通过 pB 调用的非虚函数都是基类中的,既使 pB 指向的是派生类
与“静态绑定”相对的是虚函数的“动态绑定”,即无论 pB 被声明为 Shape* 还是 Rectangle* 类型,其调用的虚函数取决于 pB 实际指向的对象类型
2 重写 (override)
在 1.2.2 中提到 override 关键字,可以避免派生类中忘记重写虚函数的错误下面以重写虚函数时,容易犯的四个错误为例,详细阐述之
class Base { public: virtual void mf1() const; virtual void mf2(int x); virtual void mf3() &; void mf4() const; // is not declared virtual in Base }; class Derived: public Base { public: virtual void mf1(); // declared const in Base, but not in Derived. virtual void mf2(unsigned int x); // takes an int in Base, but an unsigned int in Derived virtual void mf3() &&; // is lvalue-qualified in Base, but rvalue-qualified in Derived. void mf4() const; };
在派生类中,重写 (override) 继承自基类成员函数的实现 (implementation) 时,要满足如下条件:
一虚:基类中,成员函数声明为虚拟的 (virtual)
二容:基类和派生类中,成员函数的返回类型和异常规格 (exception specification) 必须兼容
四同:基类和派生类中,成员函数名、形参类型、常量属性 (constness) 和 引用限定符 (reference qualifier) 必须完全相同
如此多的限制条件,导致了虚函数重写如上述代码,极容易因为一个不小心而出错
C++11 中的 override 关键字,可以显式的在派生类中声明,哪些成员函数需要被重写,如果没被重写,则编译器会报错。
class Derived: public Base { public: virtual void mf1() override; virtual void mf2(unsigned int x) override; virtual void mf3() && override; virtual void mf4() const override; };
这样,即使不小心漏写了虚函数重写的某个苛刻条件,也可以通过编译器的报错,快速改正错误
class Derived: public Base { public: virtual void mf1() const override; // adding "virtual" is OK, but not necessary virtual void mf2(int x) override; void mf3() & override; void mf4() const override; };
小结:
- 公有继承
纯虚函数 => 继承的是:接口 (interface)
普通虚函数 => 继承的是:接口 + 缺省实现 (default implementation)
非虚成员函数 =>继承的是:接口 + 强制实现 (mandatory implementation)
-
不要重新定义一个继承自基类的非虚函数 (never redefine an inherited non-virtual function)
-
在声明需要重写的函数后,加关键字 override
-
C++ 虚函数,override,final看这一篇
2020-11-25 20:14:54C++ 虚函数看这一篇 目的是用一个指针,既能调用父类的函数,又能调用子类的函数(同名同参同返回值(返回值可以有点小差别,不是相互转换类型))。 这个对象指针,它的类型必须是父类类型。 父类成员函数必须声明... -
c++虚函数(override)和重载函数(overload)的比较
2016-11-17 19:48:313. 重载函数的调用是以所传递参数的差别作为调用不同函数的依据,虚函数是根据对象动态类型的不同去调用不同的类的虚函数; 4. 重载函数在编译时表现出多态性,而虚函数在运行时便显出多态功能。 -
C++多态--虚函数virtual及override
2017-08-16 23:35:52C++多态(polymorphism)是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。 最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,... -
C++11新特性之虚函数的override指示符
2017-09-03 23:24:532. 下面Demo中,Student类继承于People类(public公有继承),在People类中对PrintInf函数进行了虚函数的声明;为了实现多态(多态的3个条件:有继承、虚函数重写(覆盖)、有父类指针或引用指向子类对象);在父类... -
(P34)虚函数与多态:多态 ,静态绑定与动态绑定 ,虚函数 ,虚表指针 ,object slicing与虚函数 ,...
2020-10-07 22:49:06虚表指针5.object slicing与虚函数6.overload、override、overwrite 1.多态 多态性是面向对象程序设计的重要特征之一 多态性是指发出同样的消息被不同类型的对象接收时,有可能导致完全不同的行为 (1)调用同名的... -
C++笔记 15.2 虚函数
2020-09-05 19:53:17primer C++笔记 虚函数 派生类中的虚函数 override final 虚函数与默认实参 回避虚函数的机制 -
【c++】虚函数描述符override
2014-05-10 12:45:25C++11中为了帮助程序员写继承结构复杂的类型,引入了虚函数描述符override 重载虚函数 就加上关键字override 这样编译器可以辅助检查是不是正确重载,如果没加这个关键字 也没什么严重的error 只是少了编译器检查的... -
虚函数 纯虚函数 抽象基类
2020-09-30 09:41:51override:对虚函数进行重写的函数 final与override 假设声明一个基类的指针,它可以根据指向的对象类型动态的绑定对应的函数 虚函数的默认实参 如果我们通过基类的引用或指针调用函数,则使用基类中定义的默认实参 ... -
友元函数类图_C++ 虚函数和纯虚函数 virtual 友元函数和友元类 override const
2020-12-21 12:49:19继承的是:接口 (interface)普通虚函数 => 继承的是:接口 + 缺省实现 (default implementation)非虚成员函数 =>继承的是:接口 + 强制实现 (mandatory implementation)2) 不要重新定义一个继承自基类的非虚... -
虚函数、抽象类、override和final
2018-11-15 17:44:29初识虚函数 用virtual关键字说明的函数; 虚函数是实现运行时多态性基础; C++中的虚函数是动态绑定的函数; 虚函数必须是非静态的成员函数,虚函数经过派生之后,就可以实现运行过程中的多态; 一般成员函数可以... -
C++11 override重载虚函数,final
2020-09-03 01:32:00#include<iostream> using namespace std;...//对于虚函数 final 当前虚函数到此为止,子类不能对这个虚函数进行重写。 class Base { public: virtual void foo() final {} ; Base(int n) { /...
-
51单片机电子时钟设计.rar
-
LeetCode 304 二维区域和检索 HERODING的LeetCode之路
-
【Redis】Java操作Redis:Jedis 基本操作及连接池
-
数据库面试题【十五、优化查询过程中的数据访问】
-
自媒体搞笑音效和段子素材
-
35、Java中堆和栈的区别。
-
剑指06 - 旋转数组中的最小元素
-
The application could not be installed: INSTALL_FAILED_ABORTED
-
基于springboot实现表单重复提交.docx
-
297. 二叉树的序列化与反序列化
-
Graphpad Prism 9教程,不会 SPSS,也能搞定卡方检验!
-
NFS 实现高可用(DRBD + heartbeat)
-
2021年 系统架构设计师 系列课
-
linux c 通过FTP 协议上传文件 源码 亲测可用
-
基于FPGA的verilog语言的数码管显示计数程序
-
工程制图 AutoCAD 2012 从二维到三维
-
VMware vSphere ESXi 7 精讲/VCSA/VSAN
-
C++ stl标准库官方链接
-
深究字符编码的奥秘,与乱码说再见
-
C语言零基础入门(详细讲解)