c++同名函数----重载、隐藏、覆盖

一篇文章带你搞懂C++的重载、覆盖和重写!

C++继承(四)---同名隐藏(重定义)

c++同名函数----重载、隐藏、覆盖

C++中的重载,覆盖,和重定义(同名隐藏)(***含演示代码)

函数重载与函数覆盖的区别 (**)


简述overload、override和overwrite的区别

--------------------------------------------------------------

Override,OverWrite和Overload :名称翻译,混乱。

===================================

简述overload、override和overwrite的区别

overload意为重载,override意为覆盖,overwrite意为重写。从中文意思上看,并无差别,但是如下所示,给出英文定义:

    Overloading occurs when two or more methods in one class have the same method name but different parameters.
    Overriding or overwrite means having two methods with the same method name and parameters (i.e., method signature). One of the methods is in the parent class and the other is in the child class.

即overload为同一个类中,存在多个方法名相同的函数,但是他们拥有不同的参数(参数个数,类型,顺序)。

    而 override 和 overwrite 为子类和父类之间,子类和父类拥有同样的方法名和参数列表,只是将方法体重写。这是面向对象编程的多态性。

    重载规则:
    (1)包含多个同名函数,但是参数各不相同。
    (2)参数类型、参数个数、参数顺序(不同类型间)至少有一个不同。
    (3)可以改变返回值类型(不能作为重载判断依据)
    (4)可以改变访问修饰符(不能作为重载判断依据)
    (5)可以改变异常类型和数量(不能作为重载判断依据)

    重写规则:
    (1)存在于子类和父类之间
    (2)子类必须和父类的方法名和参数列表必须完全相同。
    (3)可以改变返回值类型,但子类返回值类型必须是父类返回值类型的派生类。
    (4)可以改变访问修饰符,但是子类权限只能更开放。
    (5)声明为 final 的方法不能被重写。
    (6)声明为 static 的方法不能被重写,但是可以被重新声明。
    (7)构造器不能被重写。
    (8)子类和父类在同一个包中时,子类可以重写父类所有方法(出 private 和 final)。
    (9)子类和父类在不同包中时,子类只能重写父类的 public 和 protected 的非 final 方法。
    (10)重写可以抛出任何非强制性异常,但是不能抛出新的强制性异常,或者比父类方法更广泛的异常。

    强制性异常:必须在抛出异常的部分 try catch 或者向上 throws。
    非强制性异常:用不用 try catch 和 throw 都可以。
    java 中只有 RuntimeException 是强制性异常,其余均为非强制性异常。
————————————————
版权声明:本文为优快云博主「Regent Wan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/zeno_wrj/article/details/110478916

Override,OverWrite和Overload的区别和含义

  https://blog.youkuaiyun.com/weixin_43267344/article/details/99685473

总结

1:不管是重写还是覆盖都不会影响父类自身的功能(废话,肯定的嘛,除非代码被改)。

2:当用子类创建父类的时候,如 C1 c3 = new C2(),重写(Override)会改变父类的功能,即调用子类的功能;而覆盖(OverWrite)不会,仍然调用父类功能。

3:虚方法、实方法都可以被覆盖(new),抽象方法,接口 不可以。

4:抽象方法,接口,标记为virtual的方法可以被重写(override),实方法不可以。

5:重写(override)使用的频率比较高,实现多态;覆盖用的频率比较低,用于对以前无法修改的类进行继承的时候
————————————————
版权声明:本文为优快云博主「James-Blackhu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_43267344/article/details/99685473

函数重载与函数覆盖的区别 (**)

(1)函数重载。

函数重载发生在同一个类的内部。这组函数具有相同的函数名,但是参数列表不相同

在函数调用过程中根据传入的实参类型,匹配最佳的函数并调用。

(2)函数覆盖发生在子类与父类之间。父类中定义了一个虚函数,在子类中重新实现了这个函数,并且函数在子类和父类中具有相同的函数原型(函数名、参数列表)

在调用函数过程中,根据对象的类型,调用相应类中的虚函数。

总结一下:

函数重载同一类中的不同方法,函数覆盖是不同类中的同一方法

重载函数的参数列表不同,覆盖函数的参数列表相同;

重载函数调用时根据参数类型选方法,覆盖函数调用时根据对象类型选择方法。

注意一个问题:

“名字隐藏”:指的是父类中有一组重载函数,子类在继承父类的时候如果覆盖了这组重载函数中的任意一个,则其余没有被覆盖的同名函数在子类是不可见的。例题如下:请写出下面程序的输出:

class Base
{
public:
	virtual void print(int a)
	{
		cout << "Base print int " << a << endl;
	}
 
	virtual void print(char a)
	{
		cout << "Base print char " << a << endl;
	}
 
	virtual void print(double a)
	{
		cout << "Base print double " << a << endl;
	}
};
 
class Derived :public Base
{
public:
	void print(int a)
	{
		cout << "Base print int " << a << endl;
	}
};
 
int main()
{
	Derived d;
	d.print(10);
	d.print(5.88);
	d.print('d');
	system("pause");
	return 0;
}

我们可能会认为函数重载会根据参数类型匹配最佳的函数,

而函数覆盖会根据对象的类型调用相应类中的函数,

因此参数类型为int时调用Derived类中的函数,参数为double和char类型时会调用Base类中的函数。但是事实却不是这样的,而是这样的:

 原因如下:

Derived类只覆盖了Base类中一组重载函数的一个,因此参数类型为double何char的两个重载函数对于Derived类是不可见的,但是程序没有报错,原因是double类型和char类型都可以自动转换成int类型。就是所谓的“名字隐藏”。

解决这种名字隐藏的办法有两个:

(1)在子类中不适用函数覆盖,而是给子类的方法选择一个不同的函数名,区别于父类的方法。(2)子类覆盖父类中所有的重载方法,虽然这些重载方法中在子类中和父类中的实现完全一致,但是与第一种解决办法相比这样做的好处是不添加新的函数名。

 
————————————————
版权声明:本文为优快云博主「lyl194458」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/lyl194458/article/details/88633190

C++中的重载,覆盖,和重定义(同名隐藏)(***含演示代码)

一、基础概念

    重载:函数在同一作用域中,且函数名字相同,参数列表不同。
    注意:只有返回值不同的函数不能构成重载。
    覆盖:两个函数分别在基类和子类里,基类中的函数必须是虚函数,子类必须重写父类的方法。
    注意:基类和子类的两个函数都是虚函数。虽然子类重写父类的虚函数时有时候不加virtual,但子类的函数也是虚函数。
    重定义:两个函数分别在子类和父类,两函数的函数名相同,在继承中,子类会隐藏父类的方法。
    注意:
    (1)如果派生类的函数与基类的函数同名,参数不相同,此时,不论有无virtual关键字,基类的函数都将被隐藏。
    (2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏。


二、代码演示

    函数重载:

class Base
{
public:
    int fun(int a, int b) // 参数不同。函数的返回类型可以相同也可以不相同。
    {
        return a + b;
    }
    double fun(int a, double b)
    {
        return a + b;
    }
};

int main()
{
    Base ba;
    int a = ba.fun(3, 4);
    cout << a << endl;
    double b = ba.fun(3, 4.0);
    cout << b << endl;

    return 0;
}

    覆盖(==重写)

如下方代码所示:

class Base
{

public:
    virtual void fun()  // 参数相同。不同的范围(分别位于派生类与基类);
    {
        cout << "Base::fun()" << endl;
    }
    virtual void print()
    {
        cout << "Base::fun()" << endl;
    }
};

class student : public Base
{
public:
    void fun()
    {
        cout << "student::fun()" << endl;
    }
    void print()
    {
        cout << "student::print()" << endl;
    }
};

int main()
{
    student st;
    Base* p = &st;
    p->fun();//调用的是子类重写的函数
    p->print();
    return 0;
}

    重定义(同名隐藏)(==隐藏)

class Base
{
public:
    void fun()
    {
        cout << "Base::fun()" << endl;
    }

private:
    int _b = 1;
};

//

class A : public Base
{
public:
    void fun(int a)
    {
        cout << "A:fun()" << endl;
    }
private:
    int _a = 2;
};

   

int main()
{
    A a;
    a.fun(1);//必须要给定参数,父类函数同名隐藏
    a.Base::fun();//想要调用父类方法必须加限定
    return 0;
}

重载,覆盖,以及重定义在C++中应用广泛,在今后的学习和工作中会经常遇到。
————————————————
版权声明:本文为优快云博主「ice_玖闻于世丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_42357849/article/details/106791993

一篇文章带你搞懂C++的重载、覆盖和重写!

首先我们先了解一下它们之间的区别

Overload(重载):

重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型(参数列表不同)。调用的时候根据函数的参数来区别不同的函数。有以下特征:

(1)相同的范围(在同一个类中);

(2)函数名字相同;

(3)参数不同

(4)virtual关键字可有可无;

--------

函数的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以成为函数的重载。

Override(覆盖):

是指派生类函数覆盖基类函数,有以下特征:

(1)不同的范围(分别位于派生类与基类);

(2)函数名字相同;

(3)参数相同;

(4)基类函数必须有virtual关键字

Overwrite(重写):

是值在派生类中重新对基类中的虚函数重新实现。即函数名和参数都一样,只是函数的实现体不一样,规则如下:

(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)

(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

总结1:重载和重写主要有以下的区别

(1)范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。

(2)参数区别:重写与被重写的函数参数列表一定相同,重载和被重载的函数参数列表一定不同。

(3)virtual的区别:重写的基类函数必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有。

总结2:隐藏和重写、重载有以下的区别

(1)与重载的范围不同:和重写一样,隐藏函数和被隐藏函数不在同一个类

(2)参数的区别:隐藏函数和被隐藏的函数参数列表可以相同,也可不同,但是函数名肯定要相同。当参数不相同时,无论基类中的参数是否被virtual修饰,基类的函数都是被异常,而不是被重写。

c++同名函数----重载、隐藏、覆盖

https://blog.youkuaiyun.com/weixin_41537785/article/details/81904896

《一》重载

重载的规则:

    函数名称必须相同
    参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
    函数的返回类型可以相同也可以不相同
    仅仅返回类型不同不足以成为函数的重载。
    相同的范围(在同一个类中);
    virtual 关键字可有可无。

为什么需要函数重载?

    试想如果没有函数重载机制,如在C中,你必须要这样去做:为这个print函数取不同的名字,如print_int、print_string。这里还只是两个的情况,如果是很多个的话,就需要为实现同一个功能的函数取很多个名字,如加入打印long型、char*、各种类型的数组等等。这样做很不友好!
    类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化不同的对象,那是相当的麻烦!
    操作符重载,本质上就是函数重载,它大大丰富了已有操作符的含义,方便使用,如+可用于连接字符串等!

重载函数的匹配原则:

    严格匹配,找到后就调用。
    没有找到严格匹配的函数,但是可以通过隐式转化,找到适合的重载函数。

函数重载的原理:

编译器对重载函数的命名规则为:作用域+返回类型+函数名+参数列表

比如:

void print(int i)                    -->            _ZN4test5printEi

void print(char c)               -->            _ZN4test5printEc

《二》隐藏

隐藏的定义:隐藏是指派生类的函数屏蔽了与其同名的基类函数。(看似无实际有)

隐藏规则的底层原因其实是C++的名字解析过程。

在继承机制下,派生类的类域被嵌套在基类的类域中。派生类的名字解析过程如下:

    首先在派生类类域中查找该名字。
    如果第一步中没有成功查找到该名字,即在派生类的类域中无法对该名字进行解析,则编译器在外围基类类域对查找该名字的定义。

隐藏的规则:

    不同的作用域并且有继承关系

    不论基类函数是否为virtual,只要有派生类函数与其同名但不同参,该基类函数在派生类中将被隐藏。

    基类函数非virtual,有派生类函数与此基类函数同名同参,此时该基类函数在派生类中将被隐藏。

如何访问被隐藏的成员:

    用using关键字,自定义命名空间一节提到using可将一个作用域中的名字引入另一个作用域中;它的另一个用法是”using Base::fun”,这样派生类中如果定义同名但不同参的函数,基类函数将不会被隐藏,两个函数并存在派生类域中形成新的重载,

    class Base
     
    {
     
    public:
     
      void fun1(int a){ cout<<"Base fun1(int a)"<endl; }
     
    };
     
    class Drv:publicBase
     
    {
     
    public:
     
      using Base::fun1;   //这句使基类中名为fun1的系列函数不再被株连(只可能被隐藏同名同参的一个)
     
      void fun1(char *x){cout<<"Drv fun1(char *x) !"<<endl; }
     
    };
     
    void main(){
     
      Drv dr;
     
      dr.fun(1);
     
    }

运行输出: Base fun1(int a)

    用域限定符::来定位继承自Base却被派生类隐藏的成员,如上例将dr.fun1(1);改为dr.Base::fun1(1);即可,这种方法能调用所有被隐藏的基类成员变量和函数。

《三》覆盖    (覆盖发生在虚表中,看似无实际也无)

覆盖的定义:

    不同的范围(分别位于派生类与基类);
    函数名字相同;
    参数相同;

    基类函数必须有virtual 关键字

    class Base
    {
    public:
        Base(int a) :ma(a){}
        ~Base(){}
     
        virtual void Show()
        {
            cout << "Base::Show()" << endl;
        }
        virtual void Show(int flag)
        {
            cout << "Base::Show(int)" << endl;
        }
        
    public:
        int ma;
    };
    class Derive :public Base
    {
    public:
        Derive(int b = 0) :mb(b), Base(b){}
        ~Derive(){}
        void Show()
        {
            cout << "Derive::Show()" << endl;
        }
    public:
        int mb;
    };
    int main()
    {
        Derive* pd = new Derive(10);
        Base* pbase2 = pd;
        pbase2->Show();
     
        return 0;
    }

运行结果:

此时在虚表中发生了覆盖,派生类中的show()函数覆盖了基类中的show()函数

此时派生类的内存布局:


————————————————
版权声明:本文为优快云博主「微微啦啦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_41537785/article/details/81904896

C++继承(四)---同名隐藏(重定义)

  C++继承(四)---同名隐藏(重定义)_c++继承隐藏_董HaoYu的博客-优快云博客

C++继承

多继承与单继承
单继承概念

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值