调试的错误就是编程给你最好的东西,因为在每个错误上面都标志着前进的一步。
虚函数 :关键字 virtual
本质:不是重载而是覆盖。
纯虚函数: virtual void showme ()=0;
1:不能进行任何实现。
2纯虚函数默认为抽象类。
3抽象类不能创建对象。
在C++中.cpp 还有就是.h 文件
.h 文件是头文件,在里面写类,还有就是在里面写方法,只声明方法就可以的。
.cpp在游戏和综合中主要是写方法的实现。
总结两点:.h负责声明,具体功能是在cpp 中。2.h 的文件名还有类名一致。
抽象类:不能创建对像。
虚函数与重载函数的区别:
1虚函数不能和重载函数一样修改它对的参数,返回值类型。
2虚函数只能和定义的函数一毛一样。
下午则讲到 了定义还有声明的区别。
把这个抽象类作为基类,又派生出两个子类。在子类之中把父类之中的纯虚函数重新定义了(这也是必须的),(之前我在关于继承那一篇文章之中说过菱形继承之中就是利用虚拟继承解决数据二义性问题),也就是说这里不存在二义性问题,但是这里似乎更加具体,直接在子类中把父类之中的虚函数(带有virtual关键字修饰的函数)重写了(基类之中是一个纯虚函数,派生类必须要重写它才可以实例化对象)。
简单说一下重写(或者说是覆盖,两者意思一样):如果两个成员函数处在不同的作用域之中(上面的例子是一个在父类,一个在子类),父类之中有virtual关键字修饰(这一点是必须的),而且它们的的参数相同,返回值类型也相同(这里有必要说明一中特殊情况就是协变,协变之中返回值类型可以不同),那么这样的两个成员函数就构成了重载。(派生类中的这个函数有没有virtual关键字修饰无所谓,可加可以不加,因为即使是派生类之中的这个函数,它本质上也还是一个虚函数)。
由于派生类之中对父类的纯虚函数进行了重写,因此我们可以说上述代码实现了动态绑定。使用virtual关键字修饰函数时,指明该函数为虚函数(在上面例子中为纯虚函数),派生类需要重新实现,编译器将实现动态绑定。
在使用对象的指针的时候要千万注意一下,如下面的例子,没有实现动态绑定。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
int main()
{
Person *p;
Man *pm;
Woman *pw;
p = &man; //如果你去调用其中的Man类中方法(基类之中也有同名方法),那么它会调用基类之中的方法
p = &woman; //这是因为p的类型是一个基类的指针类型,那么在p看来,它指向的就是一个基类对象,
//所以调用了基类函数。
}
最后看一下动态绑定的条件:
1、必须是虚函数 2、通过基类类型的引用或者指针调用
到这里简单地总结一下动态多态:动态多态性是在程序运行过程中才动态地确定操作所针对的对象。它又称运行时的多态性(动态多态性是通过虚函数(Virtual fiinction)实现的)。其实到了这里,对于多态这一块内容你已经有了初步的了解了,如果你只是想初步了解一下,已经足够了。但是可能还会有一些问题,不过也影响不大,毕竟只是初步认识一下,至少你明白了多态的概念以及使用上的一些注意点。如果你想搞清楚更深一层的一些问题,你可以继续阅读。
在这一层次上我们对虚函数,纯虚函数作进一步了解,动态绑定原理是什么?然后进入一个大内容---虚表的概念。
在上一个内容上我们讨论过了关于动态绑定的概念,这时候可能会有疑问,动态绑定是如何实现的呢?那么接下来我们就来说一说里面原理性的内容。
再解释之前我们还是先来理一理一些概念,这样可以更容易理解里面的内容,先做好准备工作。
首先是关于重载、重写(也可以叫做覆盖)、隐藏(或者说是重定义)这三者的有关内容,如图所示:
接下来我们再来说一说上面提到过的几个概念,上面没有展开讲,这里仔细讲一讲:
纯虚函数
在成员函数的形参后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象(虽然抽象类不能实例化对象,但是可以定义抽像类的指针)。纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。如下面代码中:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
class Person
{
virtual void Display () = 0; // 纯虚函数 protected :
string _name ; // 姓名
};
class Student : public Person
{
//在这类里面必须要对上面的Display ()方法重新定义以后Student才可以实力化对象
};