`
soboer
  • 浏览: 1310044 次
文章分类
社区版块
存档分类
最新评论

让你编写的类也有类型信息

 
阅读更多

比如说有这样一个类的继承体系:类CDerivedA和CDerivedB都继承自类CBase。如果要写一个函数传入上面类中的一个对象的引用,在函数里面我们要根据对象的类型来进行相应的处理,也就是说对不同类型的对象进行不同的处理。在这种情况下我们就需要类的对象中保存有类型信息。下面就用一个简单的例子来说明怎么让自己编写的类有类型信息。
首先,根据类的继承关系创建类型信息tag:

structlx_Base_tag{};
structlx_DerivedA_tag:publiclx_Base_tag{};
structlx_DerivedB_tag:publiclx_Base_tag{};

然后,创建一个类型特征结构:

template<typenameT>
structcategory_traits
{
typedeftypenameT::categorycategory;
};

最后,在每个类里面加上类型信息:

//为了简单起见,这里的类没有实际内容,只保存类型信息

classCBase
{
public:
typedeflx_Base_tagcategory;
};

classCDerivedA:publicCBase
{
public:
typedeflx_DerivedA_tagcategory;
};

classCDerivedB:publicCBase
{
public:
typedeflx_DerivedB_tagcategory;
};

这样,我们就可以在函数中根据对象类型的不同进行不同的处理:

//为了简单起见,这里不同的处理仅仅为输出不同的字符串

template
<typenameT>
voidTest(T&t)
{
if(typeid(typenamecategory_traits<T>::category)==typeid(lx_DerivedA_tag))
cout
<<"classDerivedA"<<endl;

if(typeid(typenamecategory_traits<T>::category)==typeid(lx_DerivedB_tag))
cout
<<"classDerivedB"<<endl;
}

上面的函数虽然实现了想要的功能,但是却不是最优方案。
根据模板的特性,在上面的例子中类型T在编译期就已经确定。但是,if语句的判断却是在运行期进行判断的。如果出现下面的代码,那么Test就会生成两个副本。

CDerivedAa;
TestA(a);

CDerivedAb;
Test(b);

这样就会造成编译出的可执行文件膨胀,而且typeid在运行期对效率也有一定的的影响。
那么有没有什么方法使得在编译期就能根据对象类型的不同而将不同的处理方法编译进可执行文件呢?当然有,那就是函数重载。函数重载的作用就是根据参数类型的不同而调用不同的函数。所以,可以引入一个重载的帮助函数:

//为了简单起见,这里不同的处理仅仅为输出不同的字符串

template
<typenameT>
voidDoTest(T&t,lx_DerivedA_tag)
{
cout
<<"classDerivedA"<<endl;
}

template
<typenameT>
voidDoTest(T&t,lx_DerivedB_tag)
{
cout
<<"classDerivedB"<<endl;
}

而真正的函数只要调用这个帮助函数就行了:

template<typenameT>
voidTest(T&t)
{
DoTest(t,typenamecategory_traits
<T>::category());
}

这样,在编译期,所有的类型都确定了,而且根据类型的不同编译器会选择不同的函数编译进可执行文件中。
通过这种方法,既不会造成编译出的可执行文件膨胀,也避免了typeid在运行期对效率的影响。

2008年10月6日更新:

国庆节前参加了公司组织的STL的高级培训,主讲人就是大名鼎鼎的侯捷。他是《STL源码分析》的作者,而这次主讲的内容也是对STL源码的分析。对我来说这也是第一次比较深入的学习STL的源码。而本文中所讲的其实就是STL里面的Traits。STL源码中到处都能看到Traits的身影,这也是实现编译期函数重载的有效方法。
下面对文中的最后一段代码进行一下解释:
1.在编译的时候T的类型已经确定;
2.代码typename category_traits<T>::category()其实就是创建一个类型为T::category的临时变量;
3.编译期根据上面的那个变量可以推导出这个变量的类型(lx_Base_tag,lx_DerivedA_tag,lx_DerivedB_tag);
4.通过上面的类型就可以判断调用哪个函数。
经过上面的几步,就实现了编译期的函数重载。
另外,对上面2中代码里的typename关键字做一个说明:如果仅仅看category_traits<T>::category这样的代码的话,是分辨不出category是什么的(有可能是一个静态变量),加上typename关键字就是明确的告诉编译器这是一个类型。

分享到:
评论

相关推荐

    建立一个名为Student的类,该类有以下几个私有成员变量:学生姓名、学号、性别、年龄。还有以下两个成员函数:一个用于初始化学生姓名、学号、性别和年龄的构造函数,一个用于输出学生信息的函数。编写一个主函数。声明一个学学生对象。然后调用成员函数在屏幕输出学生信息。

    题目:建立一个名为Student的类,该类有以下几个私有成员变量:学生姓名、学号、性别、年龄。还有以下两个成员函数:一个用于初始化学生姓名、学号、性别和年龄的构造函数,一个用于输出学生信息的函数。编写一个...

    java 类的相关代码

    1 a 声明一个Person类,有name(String类型)、age(int类型)、sex(char类型)属性。 通过构造方法进行赋值。 一个show方法,返回String类型,内容如下: 某某 男(女) 年龄 b 声明一个Student类,继承Person类,...

    Java面向对象程序设计方案练习题(1).doc

    编写Truck 卡车 类继承于Vehicles类 增加float型成员属性load 载重 还应增加成员 方法showTruck 在控制台显示卡车的信息 并编写构造方法。 在main方法中测试以上各类。 【练习题】09.构造方法与重载 定义一个网络...

    StudentTest.java

    编写Student类,并且编写一个StudentTest类,对Student类进行测试。每一个测试用例包含 number, name, maths, english, science 5种数据,用StudentTest类读取数据,并用数据构造Student类,最终打印学生信息。 ...

    深入.NET平台和C#编程

    1 编写Car类 车名 颜色 产地 实现run方法 描述汽车基本信息 2 添加带参构造函数 在构造函数中给成员赋值 通过构造函数创建对象 用run方法 3 重载run 方法 给run 传递一个int类型参数speed 最高车速 输出信息 车速...

    惠阳信息网分类信息系统1.5

    类类型,新闻栏目自定义,公告栏目名称自定义,栏目均可后台添加,删除修改 排序,均可分类到二级 栏目。 ◆会员注册及会员管理功能。 ◆网站支持会员系统,后台可以定义会员等级(普通会员和高级会员)和积分,...

    易语言编写支持库模版,动、静态版

    易源码中的自定义数据类型、类模块、组件即为支持库中的库定义数据类型。 !!!易语言通过 GetNewInf() 获取支持库信息。 !!!所以支持库必须导出这个函数。 ========== 2.支持库命令调用 ==========。 !!!...

    数据结构课件《数据结构》(C语言版)是为“数据结构”课程编写的教材,也可作为学习数据结构及其算法的C程序设计的参数教材。

    数据结构(C语言)版,在此上传希望对大家有所帮助,《数据结构》(C语言版)是为“数据结构”课程编写...本书可作为计算机类专业或信息类相关专业的本科或专科教材,也可供从事计算机工程与应用工作的科技工作者参考。

    分类信息源码2015版绿色风格 v4.5

    本程序采用ASP+ACCESS+HTML+CSS编写,是完全免费的分类信息管理系统。分类信息发布 - 会员可选择分类发布信息、不同信息采用不同表单 分类信息查询 - 可以按类别查询、搜索分类信息 会员积分系统 - 可以给各种操作...

    学生信息管理系统(实现增删改查操作)Java+Servlet+HTML+CSS+数据库

    java部分:程序基本概念、数据类型、流程控制、顺序、选择 、循环、跳转语句、变量、类、方法、实用类、JDBC、三层架构Druid连接池、Apache的DBUtils使用、Servlet等。 数据库部分:创建表、增删改查语句的书写等。 ...

    JAVA实验报告二Java面向对象程序设计.docx

    编写主程序,创建Course类的对象course,设置course的相关属性,并将属性信息打印输出。 (2)定义接口Shape,其中包括Area方法。类Circle、Square、Triangle均实现了接口Shape。定义主函数,创建元素个数为3的Shape...

    实体类生成器

    选择要生成的实体类类型,程序会根据选中的类型自动生成相对应的实体类 3.在程序左侧会显示连接的数据库列表,选择要操作的数据库,会自动加载该数据库下的表信息。 4.选择要操作的表,在右侧会显示该表的表中的...

    java 实验 类与对象

    (3)编写一个封装学生的类Student,能够描述学生的“学号”、“ 姓名”、“性别”、“年龄”、“平均成绩”等基本属性,及获取属性、修改属性的方法和打印学生基本信息的print()方法。要求生成两个学生对象,在构造...

    Spring MVC注解与数据绑定(含源码及结果图)

    1、有如下一个订单信息页面order.jsp(置于/WEB-INF/jsp目录下),按以下步骤实现一个使用POJO类型完成表单数据传输的SpringMVC数据绑定项目。 (1) 创建一个Order类来封装上述订单信息,其中各个属性的名称和数据类型...

    C# 编写的一个学生信息管理

    建立一个窗体应用程序,并建立一个学生数据库,然后单独建立了一个类,对学生信息进行查询、删除、更改等一系列操作

    ISG信息安全竞赛题目类型.docx

    ISG信息安全竞赛题目类型全文共2页,当前为第1页。ISG信息安全竞赛题目类型全文共2页,当前为第1页。ISG信息安全竞赛题目类型 ISG信息安全竞赛题目类型全文共2页,当前为第1页。 ISG信息安全竞赛题目类型全文共2页,...

    c++ 形状类Shape(派生出圆类Circle和矩形类Rectangle)

    1.建立一个形状类Shape作为基类,派生出圆类Circle和矩形类Rectangle,求出面积并获取相关信息。 具体要求如下: (1)形状类Shape (a)保护数据成员 double x,y:对于不同的形状,x和y表示不同的含义,如对于圆,...

    易语言支持库编写模板

    易语言支持库编写模板源码,支持库编写模板,SalHe_Sayings_Please_Look,GetNewInf,test_ProcessNotifyLib,完成本库命令信息,完成本库常量信息,完成本库类型信息,完成本库附加功能信息,附加功能处理函数,new库信息,new...

    最新大型门户分类信息系统免费下载

    ·自定义信息的字段,让网站更具灵活性、专业性; ·网站集成了在线支付功能,用户能够轻松的将信息置顶; ·强大功能的信息发布页面; ·超强的管理功能,能将垃圾信息出现几率将至最低; ·网站设计简洁美观、...

    实验03 Java面向对象编程1.doc

    ○1创建一个Student类,包括的域有学号,姓名,性别和年龄,另外增加一个统计学生人数的静态域count; ○2在Student类建立构造方法初始化各域的值,并统计学生人数count; ○3创建分别获得各域(学号,姓名,性别和...

Global site tag (gtag.js) - Google Analytics