看来,基于动态联编的机制,使用函数指针就可以编写出相对通用的程序模块。然而,在面向对象的程序设计中,类成为封装功能模块的基本单位。所以不仅需要对函数指针进行动态联编,更需要对类指针进行动态联编。编译器对虚拟函数采用动态联编的方式。
//编写通用函数
void DisplayNumber( CDispDecimal* DisplayFormat)
{
//调用以实参传入对象指针的虚拟函数,一某种格式输出整形数字
DisplayFormat->DisplayFormat();
}
/*C++编译器可以直接将派生类的指针转换为基类指针。虚拟函数采用动态联编,
示例代码:
//定义一个基类,名为CDispDecimal。该类封装一个
// 整型数据成员Number、一个虚拟函数virtual DisplayFormat()
#include "stdio.h" //printf()
#include "stdlib.h" //atoi()
class CDispDecimal
{
public:
CDispDecimal(int i)
{
Number=i;
}
CDispDecimal()
{
Number=0;
}
virtual DisplayFormat()
{
printf("The decimal value is %d\n",Number);
}
protected:
int Number;
};
//从基类派生出两个子类,名为 CDispOctal、CDispHexadecimal。
// 这两个类都重载基类的虚拟函数virtual DisplayFormat()
class CDispOctal : public CDispDecimal
{
public:
CDispOctal(int i)
{
Number=i;
}
CDispOctal()
{
Number=0;
}
virtual DisplayFormat()
{
printf("The octal value is %o\n",Number);
}
};
class CDispHexadecimal :public CDispDecimal
{
public:
CDispHexadecimal(int i)
{
Number=i;
}
CDispHexadecimal()
{
Number=0;
}
virtual DisplayFormat()
{
printf("The hexadecimal value is %x\n",Number);
}
};
/*重载虚拟函数要求所有函数声明完全一致,即函数名和形参列表都一致。
// 整型数据成员Number、一个虚拟函数virtual DisplayFormat()
#include "stdio.h" //printf()
#include "stdlib.h" //atoi()
class CDispDecimal
{
public:
CDispDecimal(int i)
{
Number=i;
}
CDispDecimal()
{
Number=0;
}
virtual DisplayFormat()
{
printf("The decimal value is %d\n",Number);
}
protected:
int Number;
};
//从基类派生出两个子类,名为 CDispOctal、CDispHexadecimal。
// 这两个类都重载基类的虚拟函数virtual DisplayFormat()
class CDispOctal : public CDispDecimal
{
public:
CDispOctal(int i)
{
Number=i;
}
CDispOctal()
{
Number=0;
}
virtual DisplayFormat()
{
printf("The octal value is %o\n",Number);
}
};
class CDispHexadecimal :public CDispDecimal
{
public:
CDispHexadecimal(int i)
{
Number=i;
}
CDispHexadecimal()
{
Number=0;
}
virtual DisplayFormat()
{
printf("The hexadecimal value is %x\n",Number);
}
};
/*重载虚拟函数要求所有函数声明完全一致,即函数名和形参列表都一致。
否则等同于普通函数的重载,不能实现动态联编。*/
//编写通用函数
void DisplayNumber( CDispDecimal* DisplayFormat)
{
//调用以实参传入对象指针的虚拟函数,一某种格式输出整形数字
DisplayFormat->DisplayFormat();
}
/*C++编译器可以直接将派生类的指针转换为基类指针。虚拟函数采用动态联编,
函数体内调用的DisplayFormat()将由实参决定。*/
//定义主函数
int main(int argc, char* argv[])
{
CDispDecimal Deci;
CDispOctal Octa;
CDispHexadecimal Hexa;
//如果有数字形式的命令行参数行,将其输出,否则输出0
if(argc>1)
{
/*因为这3各类都定义了int型的转换构造函数,即以int为参数的构造函数,
所以下面可以直接赋值,而无需重载“=”运算符*/
Deci=atoi(argv[1]);
Octa=atoi(argv[1]);
Hexa=atoi(argv[1]);
}
//分别以3种格式将数字输出
DisplayNumber(&Deci);
DisplayNumber(&Octa);
DisplayNumber(&Hexa);
return 0;
}
//定义主函数
int main(int argc, char* argv[])
{
CDispDecimal Deci;
CDispOctal Octa;
CDispHexadecimal Hexa;
//如果有数字形式的命令行参数行,将其输出,否则输出0
if(argc>1)
{
/*因为这3各类都定义了int型的转换构造函数,即以int为参数的构造函数,
所以下面可以直接赋值,而无需重载“=”运算符*/
Deci=atoi(argv[1]);
Octa=atoi(argv[1]);
Hexa=atoi(argv[1]);
}
//分别以3种格式将数字输出
DisplayNumber(&Deci);
DisplayNumber(&Octa);
DisplayNumber(&Hexa);
return 0;
}
输出结果: