C++ 宏、范型和RTTI 浅析

【摘要】
       RTTI(Run-Time Type Identification)是面向对象程序设计中一种重要的技术。现行的C++标准对RTTI已经有了明确的支持。不过在某些情况下出于特殊的开发需要,我们需要自己编码来实现。本文介绍了一些关于RTTI的基础知识及其原理和实现,并分析比较三者是线上的差异与联系。

【正文】

RTTI 的需求

       和很多其他语言一样,C++是一种静态类型语言。其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的要求,C++中的指针或引用(Reference)本身的类型,可能与它实际代表(指向或引用)的类型并不一致。有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就产生了运行时类型识别的要求。
C++对RTTI的支持

     C++提供了两个关键字typeid和dynamic_cast,一个type_info来支持RTTI。

     dynamic_cast操作符:它允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构安全地转换类型。dynamic_cast提供了两种转换方式,把基类指针转换成派生类指针,或者把指向基类的左值转换成派生类的引用。见下例讲述:

void company::payroll(employee *pe) {
//对指针转换失败,dynamic_cast返回NULL
if(programmer *pm=dynamic_cast(pe)){
pm->bonus(); 
}
}

void company::payroll(employee &re) {
try{
//对引用转换失败的话,则会以抛出异常来报告错误
programmer &rm=dynamic_cast(re);
pm->bonus();
}
catch(std::bad_cast){
}
}
         这里bonus是programmer的成员函数,基类employee不具备这个特性。所以我们必须使用安全的由基类到派生类类型转换,识别出programmer指针。
      typeid操作符:它指出指针或引用指向的对象的实际派生类型。
       例如:

employee* pe=new manager;
typeid(*pe)==typeid(manager) //true 
       typeid可以用于作用于各种类型名,对象和内置基本数据类型的实例、指针或者引用,当作用于指针和引用将返回它实际指向对象的类型信息。typeid的返回是type_info类型。
       type_info类:这个类的确切定义是与编译器实现相关的,下面是《C++ Primer》中给出的定义(参考资料[2]中谈到编译器必须提供的最小信息量):

class type_info {
private:
type_info(const type_info&);
type_info& operator=( const type_info& );
public:
virtual ~type_info();
int operator==( const type_info& ) const;
int operator!=( const type_info& ) const;
const char* name() const;
};

详见:http://bbs.csdn.net/topics/40414128


三者比较:

宏可以在编译前用字符替换的办法展开,减轻程序员重复编码的工作量。

c++的范型(模版)也是在编译时确定最终的程序样式,他用的办法是编译时确定类型信息。

RTTI是运行期类型信息,可以在运行时得到对象的类型信息。

我们考察一个程序,为了说明问题,我特意找了一个简单的程序,这个程序比较a和b,如果a大于b就交换他们。但是,a、b的类型并不确定可能是字符串也可能是整数还可能是复数。为了简洁和不至于造成过的混淆,我不使用操作符重载,假定任何操作都是基于对象方法的,为了完成这个函数,a、b必须支持compare(比较)和swape(交换)方法。

我们不清楚a、b的类型,如果有3种类型我们就必须写3个函数吗?那太累人了。我们用来定义这个函数好了。
#define exchange(a,b) if(a.compare(b))a.swape(b);
这样我们在使用的时候就可以直接使用exchange宏来表达这个函数,而且可以适应各种类型,只要他们都支持这两个函数就可以。

我们还可以用范型来实现这个函数
template<typename T>
void exchange(T &a, T &b)
{
  if(a.compare(b))a.swape(b)
}
我们同样达到了目的。

如果编译器支持丰富的RTTI,我们还可以用脚本语言的方式来实现他们。
exchange(a, b)
{
  if(a.compare(b))a.swape(b);
}

上面三种方式差别在哪里呢?
第一种,使用字符替换的方式,在编译前展开宏,使之成为程序中的一段代码。
第二种,在编译时,确定调用函数的参数的类型,并自动生成一个这个类型的临时函数。
第三种,在运行时根据参数的类型确定是否能够执行这段程序。
前2种都是在编译时确认的,第三种是在运行时确定的。
在程序设计中有着大量的重复代码,我们需要一种方法来提高效率,但是为什么看着结构类似的程序需要重复代码呢?最重要的原因是,传统的程序中实体(函数、变量、属性等等)在编译时都需要内存中一块确定的地址(或者相对基址的偏移)来指代,这时cpu处理方式的内在要求,而这个和程序设计时按照名字引用的思维习惯是不一致的。
我们可以用宏和模版来代替手工对每个类型的特化,但是在程序中仍然是使用地址来指代实体的。实际上每个类型的特化程序依然存在,只是在程序设计外观上不可见了。
第三种方式,使用RTTI,程序中的实体都不再是确定的地址来指代,而是通过字符串名称(或者实体表)来指代,在运行时根据名称来特化。这种方法和前2个方法是本质的不同。
使用RTTI可以在很大程度上减轻宏和静态模版带来的副作用,使程序具有更加优雅的外观。
但是,C++的宏和静态模版也不是一无是处,他用在对效率更加严格场合是非常合适的。

### 回答1: "多范型设计"是一种软件架构设计方法,它旨在在一个系统中实现不同的变换及操作,并试图最大化代码的重用性。这种方法不仅允许在设计过程中创建灵活的系统结构,还可以降低开发成本和复杂度。范型设计的核心思想是将系统分解为相互独立的部分,然后将每个部分都定义为可重用的代码块,这些代码块能够为不同的场景和应用程序提供共同的服务和功能。在设计多范型系统,开发人员通常会使用一些基于类、继承和多态等重要的构造块,这些构造块可以定义系统的核心元素和行为。范型设计的优点在于它可以提高系统的灵活性、可维护性和可扩展性,同减少了系统内部的耦合,增强了代码重用性。范型设计也有它的缺点,在实现过程中,可能会导致过度的抽象和模板化,增加了系统的复杂性,并且需要一定程度的专业知识和实践经验。综合来看,多范型设计可以让人们更好地理解系统结构和代码复用。 ### 回答2: 多范型设计(Multi-Paradigmatic Design)是指通过结合多种不同范型(Paradigms)中的最佳实践,来创新性地解决设计问题的方法和理念。范型是一种思维模式和方法论,它主要指导着人们如何看待世界、如何分析问题。在设计领域中,不同的范型有着不同的侧重点和解决问题的方式。 在多范型设计中,设计师会探索不同范型之间的相互联系和交叉点,以实现最佳的解决方案。例如,他们可能会从功能性、美学性、可用性等多个方面来考虑设计问题,以达到多方面的满足。同,设计师也会借鉴不同范型之间的优势和创新性思维,在其中创造出属于自己的设计范式。 通过多范型设计,设计师们能够跨越不同领域的边界,将来自不同范型的创意成果结合起来,从而创造出更切实可行且具有创新性的设计方案。因此,多范型设计被广泛应用于各个设计领域,并带来了更加综合和富有创意的设计成果。 ### 回答3: 多范型设计是一种设计模式,其目的是通过使用不同的范型来实现可重用和灵活的代码。C++是一种支持多范型设计的语言,因为它可以支持面向过程的编程、面向对象的编程和泛型编程。多范型设计可以增强代码的可读性和可维护性,并且可以提高软件开发的效率。 使用多范型设计可以避免重复编写相似的函数和类,同可以使代码更加灵活和可扩展。多范型设计可以使函数和类更具有通用性,并且可以避免因为特定数据类型的限制而导致的代码冗余。例如,使用模板可以避免重复编写一个函数或类的多个版本。 需要注意的是,使用多范型设计需要平衡泛化和特化。过于泛化会导致代码过于抽象和复杂,而过于特化则会导致代码的可读性和可重用性降低。因此,设计者需要根据实际需求来权衡范型的使用。 总之,多范型设计是一种强大的编程技术,它可以使代码更加可重用和灵活,并且可以提高软件开发效率。设计者需要根据实际需求灵活运用多种范型,以实现代码的最佳设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值