C++中成员函数的重载、覆盖与隐藏

首先阐述一下各自的定义:

 

一、重载

1、范围相同(在同一个类里,不能跨类)。

2、函数名字相同。

3、参数不同。

4、virtual 关键字可有可无。

 

二、覆盖

1、范围不同(派生类与基类)。

2、函数名相同。

3、参数相同。

4、基类必须有 virtual 关键字。

 

 三、隐藏

隐藏分两种情况:

(1)

1、范围不同(派生类与基类)。

2、函数名字相同。

3、参数不同。

4、virtual 关键字可有可无。

 

(2)

1、范围不同(派生类与基类)。

2、函数名相同。

3、参数相同。

4、基类没有 virtual 关键字。

 

下面我们看看重载和覆盖的示例:

 

#include <iostream>
using namespace std;

 

class CBase
{
 public:
       void f(int x) { cout<<"CBase::f(int)"<<" "<<x<<endl; }
       void f(float x) { cout<<"CBase::f(float)"<<" "<<x<<endl; }
       virtual void g(void) { cout<<"CBase::g(void)"<<endl; }
};

 

class CDerived:public CBase
{
  public:
        virtual void g(void) { cout<<"CDerived::g(void)"<<endl; }
};

 

int main(int argc, char* argv[])
{
       CDerived d;
       CBase *pBase=&d;

 

       pBase->f(10);
       pBase->f(10.10f);
       pBase->g();

 

       return 0;
}

 

输出的结果为:

CBase::f(int) 10

CBase::f(int) 10.1

CDerived::g(void)

 

这说明子类的 g(void) 函数覆盖了父类的 g(void)。

 

再看看覆盖和隐藏的示例:

 

#include <iostream>
using namespace std;

 

class CBase
{
  public:
         virtual void f(float x) { cout<<"CBase::f(float)"<<" "<<x<<endl; }
         void g(float x) { cout<<"CBase::g(float)"<<" "<<x<<endl; }
         void h(float x) { cout<<"CBase::h(float)"<<" "<<x<<endl; }
};

 

class CDerived:public CBase
{
  public:
         virtual void f(float x) { cout<<"CDerived::f(float)"<<" "<<x<<endl; }
         void g(int x) { cout<<"CDerived::g(int)"<<" "<<x<<endl; }
         void h(float x) { cout<<"CDerived::h(float)"<<" "<<x<<endl; }
};

 

int main(int argc, char* argv[])
{
       CDerived d;
       CBase *pBase=&d;
       CDerived *pDerived=&d;

 

       pBase->f(20.20f);
       pDerived->f(20.20f);

 

       pBase->g(30.30f);
       pDerived->g(30.30f);

 

       pBase->h(40.40f);
       pDerived->h(40.40f);
 
       return 0;
}

 

输出的结果为:

CDerived::f(float) 20.2

CDerived::f(float) 20.2

CBase::g(float) 30.3

CDerived::g(int) 30

CBase::h(float) 40.4

CDerived::h(float) 40.4

 

上面的例子中 子类 CDerived 的函数 f(float) 覆盖了父类的 f(float)

函数 g 和 f 依赖于指针的类型,如果是子类的指针,则隐藏了父类的函数。

 

隐藏的麻烦和解决办法:

 

#include <iostream>
using namespace std;

class CBase
{
  public:
        void f(int x) { cout<<"CBase::f(int)"<<" "<<x<<endl; }
};

 

class CDerived:public CBase
{
  public:
        void f(char *str) { cout<<"CDerived::f(char*)"<<" "<<str<<endl; }、
};

 

int main(int argc, char* argv[])
{
     CDerived *pd=new CDerived;
     pd->f(100);       // error
 
     return 0;

 

说明:语句 pd->f(100); 的本意是调用 CBase::f(int),但是 CBase::f(int) 不幸被 CDerived::f(char*) 隐藏了。由于数字 100 不能被隐式的转换为字符串,所以编译出错。

 

隐藏规则至少有两个存在的理由:

(1)  写语句 pd->f(100); 的人可能真的想调用 CDerived::f(char*) 函数,只是他把参数写错了。有了隐藏规则,编译器可以明确的指出错误,这对我们来说是一件好事。如果编译器将错就错,程序员很难发现这个错误,留下祸根。

 

(2)  假如 CDerived 类有多个基类,有时搞不清哪些基类定义了函数 f。如果没有隐藏规则,那么 pd->f(100) 可能会调用一个出乎意料的基类函数 f。尽管隐藏规则看起来不怎么有道理,但它的确能消灭这些意外。

 

解决办法: 如果在上面的例子中,一定要用 pd->f(100); 调用CBase::f(int),那么可以这样修改 CDerived 类:

class CDerived:public CBase
{
  public:
        void f(char *str) { cout<<"CDerived::f(char*)"<<" "<<str<<endl; }

        void f(int x) { CBase::f(x); }
};

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值