wordpress Ins同步,seo外包公司是啥,wordpress 路由怎么配,网上商店怎么开Virtual虚函数
在面向对象的C语言中#xff0c;虚函数#xff08;virtual function#xff09;是一个非常重要的概念。因为它充分体现了面向对象思想中的继承和多态性这两大特性#xff0c;在C语言里应用极广。多态性#xff1a;其含义就是多种形式#xff1b;将具有继承…Virtual虚函数
在面向对象的C语言中虚函数virtual function是一个非常重要的概念。因为它充分体现了面向对象思想中的继承和多态性这两大特性在C语言里应用极广。多态性其含义就是多种形式将具有继承关系的多种类型称之为多态模型因为使用者可以使用这种类型的多种形式但是不需要在意他们之间的差异。归根结底引用或指针的静态类型与动态类型的不一致是C语言支持多态性的根本原因。在派生类中覆盖了某一个虚函数可以再一次使用virtual关键字指出该函数的性质。如果将一个函数声明为虚函数那么这个函数在所有的派生类别中都是虚函数。一个派生类的函数如果覆盖了某个继承而来的虚函数则它的形参类型必须要和被覆盖的函数完全一致。同样派生类中的虚函数返回的类型必须和基类的类型是一致的但是这个存在一个例外。当类的虚函数返回的类型是类本身的指针或者引用的时候上述规则无效。什么是虚函数呢虚函数是指一个类中你希望重载的成员函数当你用一个基类指针或引用指向一个继承类对象的时候你调用一个虚函数实际调用的是继承类的版本。 ——摘自MSDN
#include cstring
#include string
#include iostream
#include stdio.h
#include conio.h
using namespace std;class Parent{public:char data[20];void Function1();virtual void Function2(); //这里的Function2是虚拟函数}parent;void Parent::Function1() {printf(This is parent,function1\n);
}void Parent::Function2() {printf(This is parent,function2\n);
}class Child:public Parent{void Function1();void Function2();
}child;void Child::Function1(){printf(This is child,function1\n);
}void Child::Function2() {printf(This is child,function2\n);
}
int main(int argc,char* argv[]){Parent *p;//定义了一个基类指针if(_getch() c){p child; // 如果用户输入一个小写的字母c指向继承类对象}else{p parent; // 否则指向一个基类对象}p-Function1(); // 这里编译时会直接给出Parent::Function1()的入口地址p-Function2(); // 注意这里执行的是哪一个Function2}为什么会有第一行的结果呢因为是用一个Parent类的指针调用函数Fuction1()虽然实际上这个指针指向的是Child类的对象但编译器无法知道这一事实直到运行的时候程序才可以根据用户的输入判断出指针指向的对象它只能按照调用Parent类的函数来理解并编译所以看到了第一行的结果。那么第二行的结果又是怎么回事呢注意到Function2()函数在基类中被virtual关键字修饰也就是说它是一个虚函数。虚函数最关键的特点是“动态联编”它可以在运行时判断指针指向的对象并自动调用相应的函数。如果在运行上面的程序时任意输入一个非c的字符结果如下请注意看第二行它的结果出现了变化。程序中仅仅调用了一个Function2()函数却可以根据用户的输入自动决定到底调用基类中的Function2还是继承类中的Function2这就是虚函数的作用。在MFC中很多类都是需要继承的它们的成员函数很多都要重载比如编写MFC应用程序最常用的CView::OnDraw(CDC*)函数就必须重载使用。把它定义为虚函数实际上在MFC中OnDraw不仅是虚函数还是纯虚函数可以保证时刻调用的是用户自己编写的OnDraw。虚函数的重要用途在这里可见一斑。PS:一定要注意“静态联翩 ”和“ 动态联编 ”的区别对于我来说若没有在VC6.0中亲自去测试凭自己的感觉当在键盘中输入“c”时因为虽然实际上这个指针指向的是Child类的对象但编译器无法知道这一事实它只能按照调用Parent类的函数来理解并编译所以我们看到了第一行的结果。第二行中调用了子类的function2完全是因为virtual 的功能virtual实现了动态联编它可以在运行时判断指针指向的对象并自动调用相应的函数。当然如果执行的是pparent; 这一句该指针很明显的是指向父类那么肯定调用的是父类的方法
final和override说明符
派生类如果定义了一个函数与基类的虚函数的名字相同但是形参列表不同这仍然是一个合法的行为需要使用关键字override来说明派生类中的虚函数。如果将某个函数指定为final则之后任何尝试覆盖该函数的操作都会引发错误。
虚函数和默认实参
虚函数使用默认实参则基类和派生类中定义的默认实参最好一致。
回避虚函数的机制
如果希望对于虚函数的调用不是动态的绑定而是强迫其执行虚函数的某一个特定的版本。可以使用作用域运算符来实现double undiscounted baseP-Quote::net_price(43);//强行调用基类中定义的函数版本而不管baseP的动态类型是什么通常情况下只有成员函数或友元函数中的代码才需要使用作用域运算符来回避虚函数的机制。如果一个派生类虚函数需要调用它的基类版本但是没有使用作用域运算符则在运行的时候该调用会被解析成对于派生类的版本自身的调用从而导致无限的递归。