当前位置: 首页 > 科技观察

C++成员函数的重载、继承、覆盖和隐藏

时间:2023-03-13 20:50:03 科技观察

一、C++成员函数的重载C++中有四种成员函数,分别是普通成员函数、virtual虚函数和const成员函数。(1)voidfunc(inta);(2)virtualvoidfunc(inta);(3)voidfunc(inta)常量;如果在一个类中声明这四个函数,什么是重复定义?哪些是过载?其中(1)(2)是重复定义,所以编译不能通过,(3)和(1)(2)是不同类型的函数,重载了。成员函数被重载的特点是:(1)作用域相同(即在同一个类定义中);(2)函数名相同;(3)参数类型、顺序或个数不同(包括常量参数和非常量函数)(4)virtual关键字是可选的。从成员函数的重载特性可以知道,(1)和(2)是重复定义。那么,为什么(3)与(1)(2)不同?因为类中的函数会自动添加一个自类指针this,所以voidfunc(inta)====voidfunc(Base*this,inta)virtualfunc(inta)====virtualfunc(Base*this,inta)voidfunc(inta)const===voidfunc(constBase*this,inta)const所以(3)可以用(1)(2)重载,因为参数有一个const。2.C++成员函数的继承#includeusingnamespacestd;classBase{public:voidf(inta){cout<<"Base::f(inta)"<usingnamespacestd;classBase{public:voidf(inta){cout<<"基础::f(inta)"<usingnamespacestd;classBase{public:voidf(inta){cout<<"Base::f(inta)"<usingnamespacestd;classBase{public:voidf(inta){cout<<"Base::f(inta)"<usingnamespacestd;classBase{public:virtualvoidf(floatx){cout<<"virtualBase::f(float)"<f(3.14f);pd->f(3.14f);pb->g(3.14f);pd->g(3.14f);pb->h(3.14f);pd->h(3.14f);}#includeusingnamespacestd;classBase{public:virtualvoidf(floatx){cout<<"virtualBase::f(float)"<f(3.14f);pd->f(3.14f);pb->g(3.14f);pd->g(3.14f);pb->h(3.14f);pd->h(3.14f);}其中vitualvoidfinsubclassDerived(floatx)是覆盖,而voidg(intx)和voidh(floatx)都是隐藏的运行结果:再看一个例子:#includeusingnamespacestd;classBase{public:virtualvoidf(inta){cout<<"virtualBase::f(inta)"<f(3);pd->f(2.5);Baseb;b.f(5);b.f(3.5);Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);}#includeusingnamespacestd;classBase{public:virtualvoidf(inta){cout<<"virtualBase::f(inta)"<f(3);pd->f(2.5);Baseb;b.f(5);b.f(3.5);Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);}父类中的voidf(doubled)隐藏了子类的virtualvoidf(inta),voidf(doubled)函数,所以在主函数Derivedd;d.f(3);d.f(2.5);Derived*pd=newDerived();pd->f(3);pd->f(2.5);Derivedd;d.f(3);d.f(2.5);Derived*pd=newDerived();pd->f(3);pd->f(2.5);只要通过Derived对象或Derived指针执行f()函数,只会执行voidDerived::f(doubled)函数。[html]Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);调用pBase->f(5)时,先到pBase类中找到对应的函数执行,因为Base类中有virtualvoidf(inta)和voidf(double)两个重载函数,因为实参是5,是int类型,所以需要调用virtualvoidf(inta)函数,因为f(inta)是虚函数,所以需要判断指向的具体对象通过pBase,也就是Derived子类,然后在Derived子类的虚函数表中找到voidf(inta)函数。因为Derived子类继承了父类Base的虚函数vituralvoidf(inta),所以输出virtualBase::f(inta);调用pBase->f(3.5)时,先去pBase类中找到对应需要执行的函数,因为Base中重载了两个函数virtualvoidf(inta)和voidf(double)class,因为实参是3.5,是double类,所以需要调用voidf(doubled)函数,因为这个函数是普通成员函数,直接输出。voidBase::f(doubled);再举一个例子:#includeusingnamespacestd;classBase{public:virtualvoidf(inta){cout<<"virtualBase::f(inta)"<f(3);pd->f(2.5);Baseb;b.f(5);b.f(3.5);Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);}#includeusingnamespacestd;classBase{public:virtualvoidf(inta){cout<<"virtualBase::f(inta)"<f(3);pd->f(2.5);Baseb;b.f(5);b.f(3.5);Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);}子类Derived中的voidf(inta)不仅覆盖了基类Base的virtualvoidf(inta),还隐藏了基类virtualvoidf(inta),voidf(doubled)函数Derivedd;d.f(3);d.f(2.5);Derived*pd=newDerived();pd->f(3);pd->f(2.5);Derivedd;d.f(3);d.f(2.5);Derived*pd=newDerived();pd->f(3);pd->f(2.5);同样,所有的子类对象或子类指针都用于调用f()函数时,只执行virtualvoidf(inta),而virtualDerived::f(inta)viewplaincopyprint?Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);Base*pBase=newDerived();pBase->f(5);pBase->f(3.5);pBase->f(5),先到Base类中找到对应的函数,和Base类中一样virtualvoidf(inta)和voidf(doubled)这两个函数是重载函数,因为实参是5,是一个int类型,所以需要调用virtualvoidf(inta)虚函数,因为函数是虚函数,所以需要判断pBase指向的具体对象,因为pBase指向的是a的一个对象子类,所以需要在子类的虚函数表中找到virtualvoidf(inta)函数,找到后执行该函数,因此输出virtualDerived::f(inta)。pBase->f(3.5),先到Base类中找到对应的函数。同样,Base类中的virtualvoidf(inta)和voidf(doubled)这两个函数是重载函数,因为实际参数是3.5,是double类型,所以我们需要调用voidf(doubled),因为这个函数是普通成员函数,所以执行输出:voidBase::f(doubled);