》 重写,重定义经常与继承和虚继承一起使用,那么我们一步一步来,先看看重写,重定义到底是什么样子的呢?

 》重载:

           1.它在同一个作用域中

           2.函数名必须相同

           3.参数个数,类型,顺序不同

           4.返回值不作要求

           5.virtual关键字不作要求

 》重写(覆盖):

            1.不在同一个作用域中(即基类与子类中)

            2.函数名相同,返回值相同,参数也相同

            3.只是在基类同名函数前必须有virtual关键字不能有static。

        这时派生类的重写函数就会覆盖基类中的同名函数。

 》重定义(隐藏):

             1.不再同一个作用域(即基类与子类中)

             2.函数名相同

             3.返回值不作要求

             4. 参数相同时,基类同名函数前不能有virtual关键字

               参数不同时,基类同名函数前有无virtual关键字不作要求。

        这时派生类的重写函数就会隐藏基类中的同名函数。

  在这里我引申一个新的概念叫做协变:当函数不在同一个作用域,函数名相同并且基类函数前有virtual关键字但是返回值返回的是基类对象的指针或者引用时就认为是协变。


举个例子:

class Base
{
public:
      virtual void f1();
      virtual void f2();
     void f3();
      void f4();
};
class Deriver :public Base
{
public :
    void f1();     //函数重写,这里的virtual可以不写,基类函数覆盖
      void f2(int x);//重定义
      char f3();     //重定义
      void f4();    //重定义
};
void Base::f1()
{
cout << "--Base-f1--" << endl;
}
void Base::f2()
{
cout << "--Base-f2--" << endl;
}
void Base::f3()
{
cout << "--Base-f3--" << endl;
}
void Base::f4()
{
cout << "--Base-f4--" << endl;
}
void Deriver::f1()
{
cout << "--Deriver-f1--" << endl;
}
void Deriver::f2(int x)
{
cout << "--Deriver-f2--" << endl;
}
char Deriver::f3()
{
cout << "--Deriver-f3--" << endl;
}
void Deriver::f4()
{
cout << "--Deriver-f4--" << endl;
}
int main()
{
Base d1, *bp;
Deriver d2;
bp = &d2;
bp->f1();
bp->f2();
bp->f4();
return 0;
}

结果:

   wKioL1cV3Qvh4D7RAAAu-HyxalA133.png

1.Derived类中的函数f1()是对Base类中函数f1()的重写,即使用了虚函数特性。

2.Derived类中的函数f2()是对Base类中函数f2()的隐藏,即重定义了。

3.因为Base类的函数f3()和f4()没有定义为virtual虚函数,所以Derived类的函数f3()和f4()是对Base::c()的重定义。

4.bp指针是一个指向Base类型的指针,但是它实际指向了一个Derived的空间,这里对pd调用函数的处理(多态性)取决于是否重写(虚函数特性)了函数,若没有,则依然调用基类。

5.只有在通过基类指针或基类引用 间接指向派生类类型时多态性才会起作用。