C++中关于隐藏的理解

引言

在使用中弄清楚隐藏的区别之后,还需要明白怎么使用。下面说以下隐藏,重写,重载的区别:
与重载的区别:

在父类与子类中,函数名相同,参数不同,无论父类中的同名函数是否含有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()之间是重写,又叫覆盖,当重写发生的情况下,父类的指针或引用指向子类的对象,通过父类的指针或引用调用父子类中被重写的函数,实际上调用的是子类的函数,这个具体得理解虚函数,多态这块,这里不再提及。以上是对函数之间关系的一种分析,接下来应该看看如何使用隐藏,隐藏使用的时候记住一句,派生类的指针或引用,对象调用子类和父类同名的函数,父类的同名函数被子类隐藏,调用的是子类的函数,当然这句话是针对于隐藏关系的函数的而言。接下来看如何应用。

隐藏的应用

下面是一个小程序,上代码:

// hideDemo.cpp : 定义控制台应用程序的入口点。
//

#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().当然这只适用于作答,真正的理解还得从书上给出的解释入手。

巩固

下面基于上面的理解,看看下面的程序:

// hideDemo.cpp : 定义控制台应用程序的入口点。
//

#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(),因为没有此时没有涉及到多态,这里是父类的对象调用的,不是父类的指针,或者引用调用。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肩上风骋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值