更新时间:2024-05-21 13:51
函数覆盖发生在父类与子类之间,其函数名、参数类型、返回值类型必须同父类中的相对应被覆盖的函数严格一致,(只有一种情况下返回值可以不一致,那就是返回自己类的引用或者指针的时候)覆盖函数和被覆盖函数只有函数体不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做函数覆盖。
覆盖函数,即在子类中用相同的函数名和签名重写父类的方法,虚函数,在子类中用相同的函数名和签名重写父类的方法(前面有virtual关键字)
总结:调用函数的时候,关键看对象的类型 。
记住是对象的类型,不管是指针还是引用(同样是对象的类型)。
好了有了对象的类型就好办了。当你用这个对象(或者是指针、引用)去调用函数时,
1:该对象(实体)即不是指针或引用的形式,可以轻松的调用函数。
2:但是当我们用引用或指针形式时,有个问题是区别指针(引用)的类型和指针(引用)所指实体对象的类型。
A:你用指针来调用某函数,若函数是非虚函数,非虚函数是静态编译的(即编译时刻确定的)。也就是说他不会去虚函数表找这个函数(因为不是虚函数),因 此调用的是指针类型的那个类的相关函数。即使派生类有这个函数(这是实际编程时的大忌!!!)。这就是 你的void FunctionA() const ;
B: 当你用这个指针去调用一个虚函数时,他就到虚函数表中,找这个名字的函数,从指针所指对象的类型(即派生类)依次向父类走,直到遇到第一个与次匹配的函数名。
class Father
{
public:
void FunctionA() const
{
}
virtual void FunctionB() const
{
}
};
class Child : public Father
{
public:
void FunctionA() const
{
}
virtual void FunctionB() const
{
}
};
2。在将父类对象的指针指向子类对象的时候 Father* father = new Child;
如father->FunctionA(),则执行的是Father中的实现;father->FunctionB(),
则执行的是Child中的实现。
3。如果直接声明子类对象,Child child;则无论child.FunctionA()还是 child.FunctionB(),执行的都是Child中的实现。
实现条件:
A.发生在不同的范围(分别位于派生类和基类中);
B.函数名相同;
C.参数相同(个数相同、顺序相同、类型相同);
D.基类的同名成员函数必须有关键字virtual修饰;