重载、覆盖与隐藏

来源:互联网 发布:python sum(axis) 编辑:程序博客网 时间:2024/05/16 13:00

这几个概念都有一个共同点:函数名称相同,所以不免让人混淆,大致的区别如下:

重载:必须在一个域中,函数名称相同但是函数参数不同,重载的作用就是同一个函数有不同的行为,因此不是在一个域中的函数是无法构成重载的,这个是重载的重要特征

覆盖:覆盖指的是派生类的虚拟函数覆盖了基类的同名且参数相同的函数,既然是和虚拟函数挂钩,说明了这个是一个多态支持的特性,所谓的覆盖指的是用基类对象的指针或者引用时访问虚拟函数的时候会根据实际的类型决定所调用的函数,因此此时派生类的成员函数可以"覆盖"掉基类的成员函数.
注意唯有同名且参数相同还有带有virtual关键字并且分别在派生类和基类的函数才能构成虚拟函数,这个也是派生类的重要特征.
而且,由于是和多态挂钩的,所以只有在使用类对象指针或者引用的时候才能使用上.
总之一句话:覆盖函数都是虚函数,反之不然~~

隐藏:指的是派生类的成员函数隐藏了基类函数的成员函数.隐藏一词可以这么理解:在调用一个类的成员函数的时候,编译器会沿着类的继承链逐级的向上查找函数的定义,如果找到了那么就停止查找了,所以如果一个派生类和一个基类都有同一个同名(暂且不论参数是否相同)的函数,而编译器最终选择了在派生类中的函数,那么我们就说这个派生类的成员函数"隐藏"了基类的成员函数,也就是说它阻止了编译器继续向上查找函数的定义....
回到隐藏的定义中,前面已经说了有virtual关键字并且分别位于派生类和基类的同名,同参数函数构成覆盖的关系,因此隐藏的关系只有如下的可能:
1)必须分别位于派生类和基类中
2)必须同名
3)参数不同的时候本身已经不构成覆盖关系了,所以此时是否是virtual函数已经不重要了
  当参数相同的时候就要看时候有virtual关键字了,有的话就是覆盖关系,没有的时候就是隐藏关系了

如以下代码


#include<stdio.h>
#include<iostream>
using namespace std;
using namespace System;


class Base

{

public:

 virtual void f(float x){ cout << "Base::f(float) " << x << endl; }

 void g(float x){ cout << "Base::g(float) " << x << endl; }

 void h(float x){ cout << "Base::h(float) " << x << endl; }

void y(int x) {cout << "Base::y(int) " << x << endl; }

};

class Derived : public Base

{

public:

 virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }

 void g(int x){ cout << "Derived::g(int) " << x << endl; }

 void h(float x){ cout << "Derived::h(float) " << x << endl; }

void y(int x,int y) {cout << "Derived::y(int ,int) " << x << y<<endl; }

};

 

int main(array<System::String ^> ^args)
{
 Derived d;

 Base *pb = &d;

 Derived *pd = &d;

 // Good : behavior depends solely on type of the object , override

 pb->f(3.14f); //运行结果: Derived::f(float) 3.14

 pd->f(3.14f); //运行结果: Derived::f(float) 3.14

 // Bad : behavior depends on type of the pointer , hide

 pb->g(3.14f); //运行结果: Base::g(float) 3.14

 pd->g(3.14f); //运行结果: Derived::g(int) 3

 // Bad : behavior depends on type of the pointer , hide

 pb->h(3.14f); //运行结果: Base::h(float) 3.14

 pd->h(3.14f); //运行结果: Derived::h(float) 3.14

pd->y(1);//错误,因为基类的成员函数y被隐藏了,永远无法被调用


}

也是你可以这么理解指针是那个类型就调用那个类的成员函数,但是如果出现如例子所示的成员函数y,虽然派生类继承了基类的y(int),但由于这个函数被派生类的y(int ,int)被隐藏了,所以pd->y(1)这样调用就会出错,也因为这个函数被隐藏了,所以永远无法被派生类使用了,要使用被隐藏的函数只能定义基类的对象或者指针

 

0 0