C++中这几个概念非常相似,很容易混淆,在编程时也很容易导致错误
“name hiding” 是指在类的继承层次中,基类和子类共享想同名字的变量或者方法,从而导致父类的名称在子类中不可见。
这种现象在c中也很普遍,比如:
int iCnt = 1;
func(int i) { int iCnt =2 };//在这个函数中,所有和iCnt相关的操作都是使用函数的局部变量,这时外部的iCnt被隐藏。
func( iCnt );
func(int i) { int iCnt =2 };//在这个函数中,所有和iCnt相关的操作都是使用函数的局部变量,这时外部的iCnt被隐藏。
func( iCnt );
下面给出一个类的实例:
class B1
{
public:
int nV;
void fun() {cout<<"Member of B1"<<endl;}
};
class B2
{
public:
int nV;
void fun(){ cout<<"Member of B2"<<endl;}
};
main()
{
B1 d1;
d1.nV=1; //objectname.objctMember, access var in D1
d1.fun();
d1.B1::nV=2; //access base class B1’s member
d1.B1::fun();
}
{
public:
int nV;
void fun() {cout<<"Member of B1"<<endl;}
};
class B2
{
public:
int nV;
void fun(){ cout<<"Member of B2"<<endl;}
};
main()
{
B1 d1;
d1.nV=1; //objectname.objctMember, access var in D1
d1.fun();
d1.B1::nV=2; //access base class B1’s member
d1.B1::fun();
}
在上面的例子中,B2的fun方法会把父类的同名、同参方法隐藏。 如果仍需要调用父类的被隐藏方法,可以通过“父类名::"来访问,如上例所示。
"overloading”被称作函数的重载”overriding“又叫函数的覆盖
区别如下:
- 函数重载指在同一个类中通过设置相同函数名称,不同的参数的多个函数实现不同的方法。
- 函数覆盖指在父类和子类中,两个函数名称和参数完全一致,其行为却是不同的
- 函数重载发生在编译期间
- 函数覆盖属于动态帮顶,发生在程序运行时
- 通过函数重载可以针对一个函数名称,根据函数的不同传入类型来多样化函数的行为
- 通过函数覆盖可以在一个继承层次的不同类型,针对同一个函数名称,实现不同的方法
可以通过下面例子加深对于函数重载、覆盖的认识
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << 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; }
};
int main()
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14 // overriding
pd->f(3.14f); // Derived::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3
}