同名隐藏
隐藏:是指派生类的函数屏蔽了与其同名的基类函数,注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。
using namespace std;
class Object
{
public:
int _num;
Object(int num):_num(num) {
cout << " Object create" << endl;
}
Object() {
cout << " Object create" << endl;
}
void fun(int x)
{
_num = x;
cout << "Object ::fun()" << endl;
}
};
class Base :public Object
{
public:
int _val;
Base() { cout << "Create Base " << endl; }
Base(int v) :Object(v), _val(v) {
cout << "Create Base " << endl;
}
void fun() {
cout << "Base ::Fun()" << endl;
}
};
int main()
{
Base base1;
Object obj1;
Base* bp = &base1;
bp->fun();//ok //函数名相同,同名隐藏,将基类的函数隐藏,
bp-> fun(10);//error //编译器无法识别,不可以像函数重载一样识别。(因为作用域不同,每个函数都在不同的类域中)
bp-> Object::fun(10);//ok,有类域的限定符指定访问
return 0;
}
代码结果:
bp->fun();//ok //函数名相同,同名隐藏,将基类的函数隐藏
以下测试代码结果:
Object* p = &base1; p->fun();
切片,p只指向Object类对象。
同名覆盖(重写)
同名覆盖,指的是在继承关系中,父类和子类的虚函数名、形参类别、返回类型相同,并是公有继承,派生类重写了这个函数。
是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类对象调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
using namespace std;
class Object
{
public:
int _num;
Object(int num):_num(num) {
cout << " Object create" << endl;
}
Object() {
cout << " Object create" << endl;
}
virtual void fun()
{
//_num = x;
cout << "Object ::fun()" << endl;
}
};
class Base :public Object
{
public:
int _val;
Base() { cout << "Create Base " << endl; }
Base(int v) :Object(v), _val(v) {
cout << "Create Base " << endl;
}
virtual void fun() {
cout << "Base ::Fun()" << endl;
}
};
int main()
{
Base base1;
Object obj1;
Object* p = &base1;
p->fun();//查虚表,调用的是Base的fun();
p->Object::fun();//静态联编,调用指定基类的fun()函数。
Base *ip=&base1;
ip->fun() //同名隐藏。
return 0;
}
p->fun();//查虚表,调用的是Base的fun();
以下是输出结果:
p->Object::fun();//静态联编,调用指定基类的fun()函数。
ip->fun() //同名隐藏。
一个小知识点:一个唯一的例外:
当父类和子类的函数返回值是其类型的指针和引用时(说明两个函数的返回类型是不同的),则也是同名覆盖!。
在这里插入代码片
函数的重载
在C++中可以为两个或两个以上的函数提供相同的函数名称,只要参数类型不同,或参数类型相同
而参数的个数不同, 称为函数重载。
在继承关系中,不存在父类和子类之间的函数的重载(作用域不同)
class Base
public:
int _val;
Base() { cout << "Create Base " << endl; }
Base(int v) : _val(v) {
cout << "Create Base " << endl;
}
virtual void fun() {
cout << "Base ::Fun()" << endl;
}
virtual int fun(int x)
{
_val = x;
cout << "Base ::Fun()" <<_val<< endl;
return _val;
}
};
int main()
{
Base base1;
Base* bp = &base1;
bp-> fun(10);
return 0;
}
以下情况得错误:参数表相同,返回值不同会报错:
三者区别:
重载和重写的区别:
(1)范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。
(2)参数区别:重写与被重写的函数参数列表一定相同,重载和被重载的函数参数列表一定不同。
(3)virtual的区别:重写的基类必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有。
隐藏和重写,重载的区别:
(1)与重载范围不同:隐藏函数和被隐藏函数在不同类中。
(2)参数的区别:隐藏函数和被隐藏函数参数列表可以相同,也可以不同,但函数名一定同;当参数不同时,无论基类中的函数是否被virtual修饰,基类函数都是被隐藏,而不是被重写。