C++ 名字重载、隐藏、覆盖
名字重载Name overloading
如果顶层函数有不同的签名,则函数名可以相同。
如果同一类中的函数有不同的签名,则函数名可以相同。
C++中允许在相同的作用域内以相同的名字定义几个不同实现的函数,可以是成员函数,也可以是非成员函数。但是,定义这种重载函数时要求函数的参数或者至少有一个类型不同,或者个数不同。而对于返回值的类型没有要求,可以相同,也可以不同。
class C { public: C( ) { … } // default constructor C( int x ) { … } // convert constructor }; void print( double d ); void print( char * ); int main( ) { C c1,c2(26);//编译过程中绑定函数调用和对应的函数体 print( 100.123); print( “100.123” ); }
名字覆盖、重置 Name overriding
若基类方法 B::m 和派生类方法 D::m 具有相同的函数签名,且基类方法 B::m 是 virtual 方法,则 D::m 重置了 B::m。
当通过基类指针或引用访问被重置的方法 m 时,需要运行时动态绑定。
覆盖(override)是指派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体不同,当派生类对象调用派生类中该同名函数时会自动调用派生类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做覆盖。
class B { public: virtual void m( ) { … } }; class D : public B { public: void m ()//重置了基类方法,仍然为虚函数 { … } }; int main( ) { B*p= new D; p -> m(); // 动态绑定 D::m() return 0; }
class B { public: void m( )//非虚函数,采用静态绑定 { … } }; class D : public B { public: void m ( ) { … } }; int main( ) { B* p=new D; p ->m( ); //静态绑定 B::m() return 0; }
名字覆盖、重置 Name overriding 条件
在父、子类的函数,即存在继承体系结构。
父类中标为virtual的成员函数。函数名字相同,参数相同。
通过父类的指针或是引用 指向或引用 一个对象,并调用虚函数。
名字隐藏 Name hiding
若基类 B 定义了非虚方法 m,同时其派生类 D 也定义了方法m,此时,我们说派生类方法 D::m 隐藏了继承自基类的同名方法 B::m 。
class B { public: void m(int x) { … } }; class D : public B { public: void m ( )//由于函数签名不同,所以二者不构成重置。 { … } }; int main( ) { D d1 ; d1.m(); // invokes D::m() d1.m(10); // ERROR d1.B::m(10); // OK return 0; }
由于函数签名不同,所以二者不构成重置。故D::m隐藏了B::m。
n函数同名的一般理由如下:
1.以Top-level函数形式定义时,形成重载,表示他们完成相同的概念操作;
2.同一个类中的非构造函数,若同名则形成重载,表示他们完成相同的概念操作;
3.一个类存在多个构造函数:default constructor, copy constructor, convert constructer, …
4.在一个类继承层次中,为支持方法多态,由基类定义虚函数,在派生类中重新定义-重置。