type trait用于平行类层次中的参数类型检查
2008-07-26 19:52
399 查看
什么是平行类层次
如以下UML图所示。Animal都需要吃(eat)食(Food), Dog只吃狗食(DogFood), Cat只吃猫食(CatFood).狗吃猫食?
Dog dog; CatFood catFood; dog.eat(catFood); // 狗吃了猫食。
解决方案
方案1:覆盖(override)eat函数
覆盖函数可定义如下:void Dog::eat(const Food& food) { If (food is NOT an instance of DogFood) 狗吠 and return; …… }
优点:狗不会误食猫食了。
缺点:只有在狗开始吃时(运行时)才知道食物是否可吃。在某些情况下,为时已晚。
方案2:添加额外接口
为Dog和Cat添加额外接口来吃食,如下图所示。从今以后Dog只能通过eatDogFood接口来吃食,Cat只能通过eatCatFood接口来吃食。优点:狗吃得安心了,不再担心被喂猫食。
缺点:在Dog和Cat中个增加了一个接口,从而增加了记忆和使用的负担。
方案3:Type trait
我们可以定义一个模板函数(template function),主人一律通过此模板函数来给Animal喂食,而无需分别对待具体Animal,如猫、狗等。模板函数可定义如下:template<class AnAnimal, class AFood> void feed(const AnAnimal& animal, const AFood& food) { animal.eat(food); }
显然需要对以上模板参数AnAnimal和AFood进行一定的约束,才能满足我们的需求。首先,AnAnimal必须是一种真正的Animal (继承于Animal)。一个简单赋值可达到目的。赋值语句如下:
const Animal& realAnimal = animal; // 编译错误如果animal不是继承于Animal.
其次,AFood必须是AnAnimal对应的食物类型, 即Animal 对应 Food, Dog对应DogFood, Cat对应CatFood. 换句话说,AFood由AnAnimal来决定,AFood可以看成是AnAnimal的一个特性。这不正是type trait所做的是吗!定义type trait如下:
template<class AnAnimal> struct AnimalFoodTrait; template<> struct AnimalFoodTrait<Animal> {typedef Food AFood;}; template<> struct AnimalFoodTrait<Dog> {typedef DogFood AFood;}; template<> struct AnimalFoodTrait<Cat> {typedef CatFood AFood;};
最后,利用这些type trait,我们可以修改那个模板函数,让其只带一个AnAnimal模板参数,AFood参数由AnAnimal推导出。
所以,最终模板函数定义为:
template<class AnAnimal> void feed(const AnAnimal& animal, const AnimalFoodTrait<AnAnimal>::AFood& food) { const Animal& realAnimal = animal; realAnimal.eat(food); }
利用这个修改过的模板函数,主人立刻(编译期)就可以知道是否喂错了食。以狗吃猫食为例:
Dog dog; CatFood catFood; feed(dog, catFood); // 狗吠,CatFood不能转化成DogFood.
相关文章推荐
- 容器中的参数类型检查
- 检查页面参数,根据返回类型不同进行不同的操作
- 考虑用类型代替参数检查
- Python参数类型检查的简单方法
- Python中实现参数类型检查的简单方法
- isNaN() 函数用于检查其参数是否是非数字值。如果是非数字值则返回true
- javascript函数参数、返回值类型检查
- python通过装饰器检查函数参数数据类型的方法
- 用于datagrid模板针对不同的数据类型的参数归总
- Goasm为啥没有类型和参数检查
- 一个可变参数类型检查的示例
- More Effective C# Item3 : 运行时检查泛型参数的类型并提供特定的算法
- Objective-C 编程语言(9)使能静态行为----类型检查、返回值和参数的类型、将派生类静态地转换为基类类型
- python通过装饰器检查函数参数数据类型的方法
- 一个可变参数类型检查的示例
- 尽可能使用泛型方法,除非需要将类型参数用于实例的字段
- Effective c++之Item 24: 当类型转换应该用于所有参数时,声明为非成员函数
- More Effective C# Item8 :尽可能使用泛型方法,除非需要将类型参数用于实例的字段中
- 测试mysql查询中参数整形和字符串类型错误索引使用情况
- linux 磁盘调度、磁盘类型、top以及iostat 参数笔记