虚函数

来源:互联网 发布:使命召唤4mac迅雷下载 编辑:程序博客网 时间:2024/06/06 07:21

虚函数

一、重写发生的条件:

1.不在同一作用域。

2.函数名相等,参数相等,返回值相等。

3.基类函数必须有virtual关键字。

重写条件满足后,父类虚函数表中的父类虚函数fun()函数的地址,会被修改成子类虚函数fun()函数的地址,下一次去父类虚函数表调用的函数就是子函数的fun(),重写是构成多态最重要的一个条件。

重写的过程看起来和隐藏很相似,其实不然,隐藏之后还是可以通过限定作用域找到被隐藏的元素,但是重写是完完全全在虚函数表里面给把它写掉了,再也找不到被重写的那个元素了。

二、继承体系同名成员函数的关系

1、重载:在同一作用域;函数名相同,参数不同;返回值可以不同

2、重写(覆盖):不在同一作用域(分别在基类和派生类);函数名相同,参数相同,返回值相同(协变例外);基类函数必须有virtual关键字;访问修饰符可以不同。

3、重定义(隐藏):在不同作用域中(分别在基类和派生类中);函数名相同;在基类和派生类中只要不构成重写就是重定义

三、总结

1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同(协变除外)。

2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。

3、只有类的成员函数才能定义为虚函数。

4、静态成员函数不能定义成虚函数,

5、如果在类外定义虚函数,只能在声明函数时加virtual,类外定义函数时不能加virtual。

6、不要在构造函数和析构函数里面调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会发生未定义的行为。

7、最好把基类的析构函数声明为虚函数。(why?析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里是因为编译器做了特殊处理。)

8、构造函数不能为虚函数,虽然可以将operator=定义为虚函数,但是最好不要将operator=定义为虚函数,因为使用时容易引起混淆。

解释:1.为什么静态成员函数不能定义为虚函数?

 因为静态成员函数是一个大家共享的资源,但是静态成员函数没有this指针,而且虚函数变只有对象才能调到,但是静态成员函数不需要对象就可以调用,所以这里是有冲突的。

2、为什么不要在构造函数和析构函数里面调用函数?

构造函数当中不适合用虚函数的原因是:在构造对象的过程中,还没有为“虚函数表”分配内存。所以,这个调用也是违背先实例化后调用的准则;