virtual 函数返回值类型 虚函数名(形参表)
{ 函数体 }
虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。
当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。
动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数,其格式:
指向基类的指针变量名->虚函数名(实参表)
或 基类对象的引用名. 虚函数名(实参表)
虚函数的实例:
#include<iostream.h>
class Cshape
{ public: void SetColor( int color) { m_nColor=color;}
void virtual Display( void) { cout<<"Cshape"<<endl; }
private:
int m_nColor;
};
class Crectangle: public Cshape
{
public:
void virtual Display( void) { cout<<"Crectangle"<<endl; }
};
class Ctriangle: public Cshape
{
void virtual Display( void) { cout<<"Ctriangle"<<endl; }
};
class Cellipse :public Cshape
{
public: void virtual Display(void) { cout<<"Cellipse"<<endl;}
};
void main()
{
Cshape obshape;
Cellipse obEllipse;
Ctriangle obTriangle;
Csquare obRectangle;
Cshape * pShape[4]=
{ &obShape, &obEllipse,&obTriangle, & obRectangle }; // 基类指针可以指向子类
for( int I= 0; I< 4; I++)
pShape[I]->Display( );
}
本程序运行结果:
Cshape
Cellipse
Ctriangle
Crectangle
所以,从以上程序分析,实现动态联编需要三个条件:
1、 必须把动态联编的行为定义为类的虚函数。
2、 类之间存在子类型关系,一般表现为一个类从另一个类公有派生而来。
3、 必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。
好处:
CWinApp* pApp = AfxGetApp(); // in winmain.cpp
pApp->InitApplication(); // call child class function!
My example:
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class BaseDraw
{
public:
void virtual DrawFunc (void) {cout<< "Base Draw"<<endl;}
};
class ChildDraw: public BaseDraw
{
public:
void virtual DrawFunc (void) {cout<< "Child Draw"<<endl;}
};
class GrandChildDraw: public ChildDraw
{
public:
void virtual DrawFunc (void) {cout<<"GrandChild Draw"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
BaseDraw a;
ChildDraw b;
GrandChildDraw c;
BaseDraw *p[3]; // Base class pointer
p[0] = &a; // Base class pointer points to Base object, child object, and grandchild object
p[1] = &b;
p[2] = &c;
p[0]->DrawFunc(); // Output Base Draw
p[1]->DrawFunc(); // Output Child Draw
p[2]->DrawFunc(); // Output GrandChild Draw
return 0;
}