c++中重载,覆盖和隐藏的区别

26 篇文章 0 订阅

一:重载
在c++中把几个语义,功能相似的几个函数用同一个函数名表示;
为什么要重载呢?
1:函数名被重载,函数重载便于记忆,提高了函数的易用性,
如:

void fun(int );
void fun(float);
void fun(char);

2:C++类中的构造函数需要重载机制,c++规定类的构造函数的名字必须与类名相同;那么如何实现几种不同的方法来创建对象,这就需要重载机制来实现;
二:重载是如何实现?
几个同名的重载函数仍然是不同的函数,但是在底层都是二进制执行程序中是不允许有同名函数出现,那么如何实现:参数列表和返回值。
参数列表包括参数的类型和数目;
误区:
并不是函数名相同的函数就能构成重载如:全局函数和类的成员函数同名但是却不能构成重载,因为他们的作用域不同;

void Base()  //全局函数:文件作用域
{
    cout << "Base1() " << endl;  
}
class A
{
public:
    void Base() //成员函数:类域
    {
        cout << "Base2()" << endl;
    }
};
int main()
{
    A a;
    a.Base();
    a.fun();
    system("pause");
    return 0;
}


那么如何访问全局函数呢?为了与成员函数区别我们加上作用域解析运算符::
如:

void A::fun()
{
  ::fun();
}

成员函数被重载的特征:
1:具有相同的作用域(或者在一个类域中)
2:函数名相同
3:参数列表可不同
4:virtual关键字可有可无
三:覆盖(重写):
派生类重新实现了(或者改写)了基类的成员函数;
特征:
1:不同的作用域;
2:参数列表完全相同
3:基类函数必须是虚函数(在类的成员函数前面加上virtual关键字,则这个成员函数就是虚函数)

class Base
{
public:
    void fun(int x)
    {
        cout << "Base::fun(int)" << x << endl;
    }
    void fun(float x)
    {
        cout << "Base::fun(float)" << x << endl;
    }
    virtual    void foo()
    {
        cout << "Base::foo()" << endl;
    }
protected:
    int _b;
};
class Driver :public Base
{
public:
    virtual    void foo()
    {
        cout << "Driver::foo()" << endl;
    }
protected:
    int _d;
};
int main()
{
    Driver d;
    Base*b = &d;
    b->fun(5); //重载了Base::fun(int)
    b->fun(3.14f);//重载了Base::fun(float)
    b->foo();//派生类的重新实现了基类的的成员函数Driver::foo()

    system("pause");
    return 0;
}


(1)virtual关键字告诉编辑器,派生类中相同的成员函数放到虚表vftable中,并且把基类的成员函数覆盖;
(2)虚函数的覆盖有两种:完全重写和扩展,扩展是在实现重写之后,又增加新的功能。
这里写图片描述
四:隐藏(重定义)
隐藏式派生类的函数屏蔽了基类的同名函数;
隐藏规则:
1:如果派生类的函数和基类的函数相同,参数列表不同,无论有无virtual关键字,基类的函数都将被隐藏(与重载的区别)
2:如果派生类的函数和基类的函数相同,参数列表相同,基类无virtual关键字,基类的函数都将被隐藏

class Base
{
public:
    virtual void fun(int x)
    {
        cout << "Base::fun(int)" << x << endl;
    }
    void func(float x)
    {
        cout << "Base::fun(float)" << x << endl;
    }
    void foo()
    {
        cout << "Base::foo()" << endl;
    }
protected:
    int _b;
};
class Driver :public Base
{
public:
    virtual void fun(int x)
    {
        cout << "Driver::fun(int)" << x << endl;
    }
     void func( int x)
    {
        cout << "Driver::func(int)" << x << endl;
    }
    void foo()
    {
        cout << "Driver::foo()" << endl;
    }
protected:
    int _d;
};
int main()
{
    Driver d;
    Base*b = &d;
    Driver*pd= &d;
    b->fun(5); //基类的成员函数Base::fun(int)被覆盖
    pd->fun(5);//Driver::fun(int);

    b->func(3.14f); //Base ::func(flour );
    pd->func(3.14f);//Driver::func(flour);


     b->foo();//Base ::foo();
    pd->foo(); //Driver::foo();

    system("pause");
    return 0;
}

这里写图片描述
b和pd都是指向同一块地址,为什么结果却是不同的呢?这里面就是隐藏机制的作用,是派生类屏蔽了基类的同名函数。
隐藏的两个理由:
(1):写pd->f(5) 的人可能真的想调用Derived::f(char *)函数,只是他误将参数写错了。有了隐藏规则,编译器就可以明确指出错误,这未必不是好事。
(2):假如Driver有多个基类,有时弄不清楚那个基类定义了函数f,那么pd->f()可能回调一个意外的基类f。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值