C++面向对象的继承特性::派生类和基类的同名成员问题
1.派生类中再实现一个基类中的方法
派生类和基类中各自实现一个内容不同但函数原型完全相同的方法会怎么样?
代码实验:
#include<iostream>
using namespace std;
class person
{
public:
string name;
int age;
void info(void)
{
cout<<"person info()."<<endl;
}
};
class man:public person
{
public:
bool male;
void info(void)
{
cout<<"man info()."<<endl;
}
};
int main(int argc,char**argv)
{
person jack;
jack.info();
man tom;
tom.info();
return 0;
}
输出:
person info().
man info().
结论是:基类对象调用的是基类的方法,派生类对象调用执行的是派生类中重新提供的方法,就好像派生类中同名同参方法替代掉了基类中的方法,这种现象叫做重定义(redefining
),也有人叫做隐藏。
隐藏特性生效时派生类中实际同时存在2份同名同参(但在不同类域名中)的方法,两个同时都存在,只是一个隐藏了另一个(新的隐藏旧的)。
2.派生类中访问被隐藏的基类方法
派生类对象直接调用时,隐藏规则生效,直接调用的肯定是派生类中重新实现的那一个方法。
想在外部通过派生类对象访问被隐藏的基类方法的一种途径是:将派生类对象强制类型转换成基类的类型,再去调用则这时编译器认为是基类在调用,调用的是基类那一个,隐藏规则被绕过了。
而在派生类内部,使用父类::方法()
的方式可以强制绕过隐藏规则,从而调用父类实现的那一个方法。
举个栗子:
class man:public person
{
public:
bool male;
void info(void)
{
cout<<"man info()."<<endl;
}
void test(void)
{
//info(); //等于this->info(),调用的还是man的info
person::info(); //这样可以显式指定调用基类person的info(),绕过了隐藏规则
}
};
int main(int argc,char**argv)
{
man tom;
tom.test();
return 0;
}
person info().
3.注意和总结
基类对象调用的是基类的方法,派生类对象调用执行的是派生类中重新提供的方法。其实不止成员方法,成员变量也遵循隐藏规则。
隐藏规则本质上是大小作用域内同名变量的认领规则问题,实际上2个同名成员都存在于当前派生类的对象内存中的。隐藏(重定义redefining
)、重载(overload
)、重写(override
又叫覆盖),这三个概念一定要区分清楚。