引言
在使用中弄清楚隐藏的区别之后,还需要明白怎么使用。下面说以下隐藏,重写,重载的区别: 与重载的区别:
在父类与子类中,函数名相同,参数不同,无论父类中的同名函数是否含有virtual关键字,都是隐藏;
与重写的区别:
在父类和子类中,函数名相同,参数相同,父类中的同名函数没有virtual关键字,为隐藏。
示例
下面举例说明:
class Base
{
public:
void funA(){cout<<"funA()"<<endl;}
virtual void funB(){cout<<"funB()"<<endl;}
};
class Heri:public Base
{
public:
void funA(){cout<<"funA():Heri"<<endl;}
void funA(int a){cout<<"funA(int a):heri"<<a<<endl;}
void funB(){cout<<"funB():heri"<<endl;}
};
以上示例中,基类中的函数funA()与派生类中的函数funA()之间是隐藏,其函数名相同,参数相同,存在于派生类于子类中,且基类中的funA()函数前没有virtual关键字,故为隐藏。基类的函数funA()与派生类中的函数funA(int a)函数名相同,参数不同,存在于基类和派生类中,无论基类有没有关键字virtual两个函数之间也是隐藏,基类函数funB()与派生类函数funB()之间是重写,又叫覆盖,当重写发生的情况下,父类的指针或引用指向子类的对象,通过父类的指针或引用调用父子类中被重写的函数,实际上调用的是子类的函数,这个具体得理解虚函数,多态这块,这里不再提及。以上是对函数之间关系的一种分析,接下来应该看看如何使用隐藏,隐藏使用的时候记住一句,派生类的指针或引用,对象调用子类和父类同名的函数,父类的同名函数被子类隐藏,调用的是子类的函数,当然这句话是针对于隐藏关系的函数的而言。接下来看如何应用。
隐藏的应用
下面是一个小程序,上代码:
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
class Base
{
public:
void fun1(){cout<<"base:fun1()"<<endl;fun();}
virtual void fun(){cout<<"base:fun()"<<endl;}
};
class Deriverd:public Base
{
public:
virtual void fun1(){cout<<"deriverd:fun1()"<<endl;}
void fun(){cout<<"deriverd:fun()"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
Base *pb = new Deriverd;
pb->fun1();
system("pause");
return 0;
}
上面是一个小程序,输出结果为: 之所以输出是上面的结果是因为main函数中创建了父类的指针指向了子类的对象,然后通过父类的指针调用具有隐藏关系的fun1()函数,该函数在使用时记住一句“派生类的指针,引用,对象调用父类或者派生类中的同名函数,调用的是子类的函数”,这句话一听就会被误解,pb->fun1();以为调用的是子类的函数fun1(),实际并不是,上句话有一个前提,是派生类的对象或引用,指针进行调用,而这里是父类的指针调用,这样的解释过于牵强,我总结出的经验就是,隐藏关系的函数,谁调用就用谁的函数,按照正常的函数调用使用便可得正确的结果,这里是父类指针调用,就用父类的函数fun1().当然这只适用于作答,真正的理解还得从书上给出的解释入手。
巩固
下面基于上面的理解,看看下面的程序:
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
class Base
{
public:
void fun1(){cout<<"base:fun1()"<<endl;fun();}
virtual void fun(){cout<<"base:fun()"<<endl;}
};
class Deriverd:public Base
{
public:
virtual void fun1(){cout<<"deriverd:fun1()"<<endl;}
void fun(){cout<<"deriverd:fun()"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
Base *pb = new Deriverd;
pb->fun1();
Deriverd de;
de.fun1();
Base b;
b.fun1();
system("pause");
return 0;
}
输出结果: 定义派生类对象Deriverd de;通过派生类对象调用fun1(),这里调用的是派生类自己的函数fun1(),应了那句“派生类的对象,指针,引用调用派生类和基类的同名函数,调用的是派生类的函数,父类的函数被隐藏”,定义基类对象 Base b;通过对象b调用函数fun1(), 调用的是基类的函数fun1().然后在fun1()中输出base:fun1(),接着调用函数fun(),这里的函数fun()调用的是基类自身的函数fun(),因为没有此时没有涉及到多态,这里是父类的对象调用的,不是父类的指针,或者引用调用。
|