[置顶] 关于C++虚函数自己的理解

首先虚函数是为了实现多态的,统一接口。其中我就虚函数的性质做一些讲解,希望能够帮助大家。

在类的继承中有时为了统一接口,[置顶] 关于C++虚函数自己的理解_第1张图片

在内存中地址是整型,可以将类的地址转化成一个2维指针,在通过该地址 寻找虚函数地址。函数出现((Fun)*(*pVta+1))();就不足以为怪了。

在看看具体的代码吧!

#include"iostream.h"
#include"string.h"

class XS
{
public:
 virtual void dispXM()=0;   // 纯虚函数,区别就是抽象的,不需要给出具体代码,只要给出接口就行
 virtual void dispXB()=0;
 virtual void dispNL()=0;
};

class CZS:public XS   //  继承XS类 并实现函数接口,说明该类不是抽象类
{
public:
 CZS(char * m="张三",int b=1,int n=14);
 void dispXM();
 void dispXB();
 void dispNL();
protected:
 char xm[9];
 int xb,nl;
};

CZS::CZS(char*m,int b,int n)
{
   strcpy(xm,m);
   xb = b;
   nl = n;
}

void CZS::dispXM()
{
 cout<<"姓名:"<<xm<<endl;
}
void CZS::dispXB()
{
 if(1 == xb)
 {
  cout<<"性别:男"<<endl;
 }
 else
 {
  cout<<"性别:女"<<endl;
 }
}

void CZS::dispNL()
{
 if(nl > 0)
 {
  cout<<"年龄:"<<nl<<endl;
 }
 else
 {
  cout<<"不合法"<<endl;
 }
}
class GZS:public XS{
public:
 GZS(char * m="张三",int b=1,int n=17);
 void dispXM();
 void dispXB();
 void dispNL();
protected:
 char xm[9];
 int xb,nl;
};

GZS::GZS(char*m,int b,int n)
{
   strcpy(xm,m);
   xb = b;
   nl = n;
}

void GZS::dispXM()
{
 cout<<"姓名:"<<xm<<endl;
}
void GZS::dispXB()
{
 if(1 == xb)
 {
  cout<<"性别:男"<<endl;
 }
 else
 {
  cout<<"性别:女"<<endl;
 }
}

void GZS::dispNL()
{
 if(nl > 0)
 {
  cout<<"年龄:"<<nl<<endl;
 }
 else
 {
  cout<<"不合法"<<endl;
 }
}
class DXS:public XS{
public:
 DXS(char * m="张三",int b=1,int n=20);
 void dispXM();
 void dispXB();
 void dispNL();
protected:
 char xm[9];
 int xb,nl;
};
DXS::DXS(char*m,int b,int n)
{
   strcpy(xm,m);
   xb = b;
   nl = n;
}

void DXS::dispXM()
{
 cout<<"姓名:"<<xm<<endl;
}
void DXS::dispXB()
{
 if(1 == xb)
 {
  cout<<"性别:男"<<endl;
 }
 else
 {
  cout<<"性别:女"<<endl;
 }
}

void DXS::dispNL()
{
 if(nl > 0)
 {
  cout<<"年龄:"<<nl<<endl;
 }
 else
 {
  cout<<"不合法"<<endl;
 }
}


void displayP(XS *xs)   // 实现多态性,通过传得对象,输出对应对象的参数
{
 xs->dispXM();
 xs->dispXB();
 xs->dispNL();
}

void displayR(XS &xs)  // 通过对象的引用
{
   xs.dispXM();
   xs.dispXB();
   xs.dispNL();
}

typedef void (*Fun)(void);  // 函数的指针定义,函数的指针的指针

void main()
{
 

    CZS czs("赵一",1,12);
    GZS gzs("钱二",0,15);
    DXS dxs("孙三",1,18);


   XS *p;//定义抽象基类的指针变量p
   p=&czs;//将初中生对象czs的地址赋给p
   displayP(p);


   p=&gzs;//将高中生对象czs的地址赋给p
    displayP(p);


   p=&dxs;//将大学生对象czs的地址赋给p
    displayP(p);
   cout<<"\n----------------------------------------\n";


   XS &r1=czs;//定义抽象基类的引用变量r1为czs的别名
   displayR(r1);


   XS &r2=gzs;//定义抽象基类的引用变量r2为czs的别名
   displayR(r2);


   XS &r3=dxs;//定义抽象基类的引用变量r3为czs的别名
   displayR(r3);
   cout<<"\n----------------------------------------\n";

   int** pVta = (int**)&dxs;

    ((Fun)*(*pVta+1))();  // 指定虚函数
}

 

现在讲讲类中的具体有什么东东,[置顶] 关于C++虚函数自己的理解_第2张图片

编译器会为虚函数维护一个虚函数表,可以通过类的地址,轻松的找到虚函数的入口地址。通过指针的形式或数组的形式((Fun)*(*pVta+1))(); 

 

讲讲关于多态的实现,我们发现通过基类的指针对象,当子类对象的地址赋给该指针对象,由于虚函数,该指针就指向了自己类的函数,这样的向上映射,就实现了函数的多态

也就是函数体只需要给出基类对象的指针对象,就可以对子类进行相关操作。函数段为:

void displayP(XS *xs)   // 实现多态性,通过传得对象,输出对应对象的参数
{
 xs->dispXM();
 xs->dispXB();
 xs->dispNL();
}

在给出CZS类的函数覆盖的图片[置顶] 关于C++虚函数自己的理解_第3张图片

但注意,不是虚函数,编译器不会安排函数表的,如果对非虚函数类进行

((Fun)*(*pVta+1))();  虽然编译的时候不报错,但运行的时候肯定报错,原因是找不到这个函数的入口地址。

 

关于虚函数的理解就讲到这里了。。。希望大家多多交流指正。。。。

 

留住最真的于2012.11.09 0:30写~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

你可能感兴趣的:([置顶] 关于C++虚函数自己的理解)