C++中概念区分:Overload, Override, Hide


区分:overload, override, Hide

  • Overload: 重载,指函数同名,但是参数个数不同、或者参数类型不同的多个实现。(如果参数相同但是仅仅返回值不同不是重载,编译器会报错。)
编译器判断重载函数:
  • 第一步,是确定该调用中所考虑的重载函数的集合,该函数集合被称为候选函数(candidant function)。所谓候选函数就是与被调用函数同名的函数。
  • 第二步,分为两动作:第一个动作是编译器从第一步选出的候选函数中调出可行函数(viable function)。可行函数的函数参数个数与调用的函数参数个数相同,或者可行函数的参数可以多一些,但是多出来的函数参数都要有相关的缺省值;第二个动作是根据参数类型的转换规则将被调用的函数实参转换(conversion)成候选函数的实参。这里本着充分利用参数类型转换的原则,换句话说,尽可能的使用上参数类型转换。当然转换要以候选函数为转换的目标。如果依照参数转换规则没有找到可行函数,则该调用就是错误的,则说没有函数与调用匹配,属于无匹配情况(no match function)。
  • 第三步,从第二步中选出的可行函数中选出最佳可行函数(best match situation)。在最佳可行函数的选择中,从函数实参类型到相应可行函数参数所用的转化都要划分等级,根据等级的划分(ranked),最后选出最佳可行函数。
  • Override:(想不到比较贴切的翻译)指在继承时,父类函数声明为 virtual , 子类重新声明和实现该函数(函数名和参数完全相同,返回值不做约束)。子类该函数可以声明为 virtual ,也可以不加,不做限制,但是如果该子类还会继续被重载,则最好也声明为 virtual 。正是因为有virtual和Override的机制,C++才能够实现多态。( virtual机制是编译器使用虚表(vtable)和虚指针实现的,虚表维护一个类的虚函数指针列表。当一个对象的某个虚函数被调用的时候,对象通过它自身的虚指针去虚表中查找并决定调用的是哪个函数。注意:关于虚表和虚指针的实现不是C++标准规定的,不同的编译器厂商可能采用不同的实现策略。具体的实现,可以单独一期博客讲解。)
  • Hide:继承结构中的函数隐藏,指父类中声明了函数,子类中声明和定义了函数名一样但是参数不一样的函数,不管父类中该函数是否声明为vitual,此时子类中的同名但不同参数的函数会完全隐藏父类的函数。

class Super
{
public:
    virtual void go() { cout << "go() called on Super" << endl; }
     virtual  void go(int i) {cout<<"go(int i) called ono Super<<endl;"}
};

class Sub : public Super
{
public:
    void go() { cout << "go() called on Sub" << endl; }
};

Sub mySub;
mySub.go(); // output: go() called on Sub
int i= 5;
mySub.go(i);//Error, "void go(int i)" has been hidden

如果需要解决这个问题需要在子类中声明如下:
class Sub : public Super
{
public:
    using Super::go;
    void go() { cout << "go() called on Sub" << endl; }
};
当然这样的声明也会导致安全问题,因为它将让所有父类的同名函数在子类中可见,如果这不是你所希望的,你需要避免使用using声明,同时将你需要子类可见的函数在子类中进行Override。

注释:
发现很多人引用了我的这篇文章,但是都注明的是原创。在此抱歉的通知各位,最后的Hide原来的内容是错误的,现在本文已经修改,你们也记得更新,不要“害人”哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++,我们可以使用关键字来隐藏、覆盖和重载成员函数。 1. 隐藏(Hide):当派生类定义了与基类同名的成员函数时,基类的成员函数将被隐藏。可以使用作用域解析运算符(::)来访问被隐藏的基类成员函数。 ```cpp class Base { public: void foo() { cout << "Base::foo()" << endl; } }; class Derived : public Base { public: void foo() { cout << "Derived::foo()" << endl; } }; int main() { Derived d; d.foo(); // 输出 Derived::foo() d.Base::foo(); // 输出 Base::foo() return 0; } ``` 2. 覆盖(Override):当派生类定义了与基类同名、同参数列表的成员函数时,称为覆盖。在派生类对象上调用该函数时,将执行派生类的实现而不是基类的实现。 ```cpp class Base { public: virtual void foo() { cout << "Base::foo()" << endl; } }; class Derived : public Base { public: void foo() override { // 使用 override 关键字显式声明覆盖 cout << "Derived::foo()" << endl; } }; int main() { Derived d; Base* b = &d; b->foo(); // 输出 Derived::foo() return 0; } ``` 3. 重载(Overload):在同一个作用域内,可以定义多个同名函数但参数列表不同,称为重载。编译器根据函数调用时所传递的参数类型和数量来决定调用哪个函数。 ```cpp class MyClass { public: void foo(int x) { cout << "foo(int): " << x << endl; } void foo(double x) { cout << "foo(double): " << x << endl; } }; int main() { MyClass obj; obj.foo(10); // 输出 foo(int): 10 obj.foo(3.14); // 输出 foo(double): 3.14 return 0; } ``` 希望以上解释能够帮助到你!如果你有更多的问题,请继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值