C++语言中的元类编程(一)

来源:互联网 发布:怎么样申请淘宝网店 编辑:程序博客网 时间:2024/06/06 02:27

真是光阴似箭啊!距上次写博客已有4年,现在重新再看自己之前的文章,发现自己以前过于执着于一些语言特性上的编程技巧,虽然这些技巧是有用的,但却不是编程的核心。正如同西方油画与中国画,在工具、画风、技法上完全不同,但都是为了表达画家对事物的一种理解、抽象、感悟和升华!当面对一副好的美术作品,无论是画家还是普通人(只要他喜爱美术),他就能从这副作品中感受到一种冲击力。而编程也是一样,无论你使用的哪种语言,最核心的是,对于所要处理的问题或任务,你是否能够以一种美妙的形式加以描述或刻画,并使之正确运行!而任何一种设计与编程的方法或技巧,都是为了更好的达到以上目的而提出的,因此现在的我,打算抛开一种语言的特性,去尝试总结一些更加有意思的,更加通用的设计与编程方法,这些方法都是从我个人的工作与学习中获得的。受限于本人的学识,我不可能进行系统的论述,只是希望能起到抛砖引玉的作用, 并寻得志同道合的伙伴。如果恰好能对某位受困于类似问题的朋友有所启发和帮助,那就再好不过了!

感叹写完了,现在进入正题。这次选取的题目可能对于一些具有C++语言编程经验的朋友会有些陌生,而这正是我的目的,因为我希望读完这篇文章的朋友可以有一种“啊,原来C++语言还可以这样”的奇妙感觉!因此我假定你是一位对C++语言有一定的基础,但对元类编程的思想了解不多或应用很少的朋友。

首先,我们需要了解什么是元类编程,简单的说,元类编程就是使用“元类”进行编程。那么什么是“元类”呢?按照教科书上的解释,“元类”就是一个关于类的类,然而什么是“关于类的类”呢?我们仍然难以得其要领。让我先问一个问题:请列举一下人类和动物的区别?你可能会说:“人是直立行走,而动物是四肢行走;人会说话,而动物只会叫;人会使用工具,而动物只会利用身体,……”(这里只是打个比方,动物权益者请不要来争辩:“动物也有能直立行走的,动物也能交流,动物也有会使用工具的,……”)。很好,现在让我们换一种形式再来概括一下:

(人类,直立行走,会说话,会使用工具,……)

(动物,四肢行走,会叫,会使用身体,……)

请注意以上形式中,括号中的内容很明显可以使用一个数据结构来表示,而如果我们把“人类”和“动物”看做两个类的话,那么这个数据结构描述的就是这个两个类的特性(或区别),利用这个数据结构,我们还可以刻画更多不同的类,比如:

(昆虫,六腿行走,会传递信息素,会飞,……)

(鸟类,有翅膀和羽毛,会叫,会飞,……)

……

那么对于这个数据结构,我们就认为它是一个“元类”(在我们的例子中,我们可以称它为“生物”元类)。可见,元类是一种比类更高级的抽象,可以用于描述一组(通常数目是不确定的)相似而又不同的类(甚至连属性、方法、接口也可以不同)。现在我们应该能对元类有一个比较简单的认识了。

接下来,你可能会问,为什么要使用元类?这个问题其实就和你为什么选择使用C++编程一样,在某些特定的(通常也是比较复杂的)情况中,元类能够提供一种更加强大也更加有效的编程思路和程序组织方法,在适合使用元类的场景中,使用元类比不使用元类的代码通常更紧凑、更高效、更易于检查错误、也更稳定。当然它更加抽象,对于初次接触元类的朋友来说,可能更难理解,但是一旦你抓住了它的要领,其实使用元类编程的代码会更易读,更易于维护。你可能不会马上相信我以上所说的种种好处,没关系,所谓“实践出真知”,让我们先来看看如何应用元类编程吧。

其实在C++的标准库中,不乏元类编程的实例,不知你是否注意到,在众多的C++模板库中,通常有一个后缀是_traits的模板参数,这个参数就是一个元类,它定义了模板实例类的属性和方法的特性,用户可以在保持接口不变的情况下,自定义一个traits类(相当于实例化一个元类)来扩展标准模板的能力。当然,在标准库中,除了traits还有很多其它类型的元类,而所有使用模板来实现元类编程的技术就称之为编译期元编程。目前网上和书店有大量重点研究和讨论编译期元编程技术的书和文章,这里就不再班门弄斧了。

既然有编译期的元类编程,自然就有运行时的元类编程,而本文想探讨的正是这方面的方法和技巧。为什么想探讨运行时元类编程呢?首先是我觉得这方面的资料太少,希望自己能写些有特色的东西;其次,编译期元编程由于用到了大量模板的特性,使得它成为了一种语言相关的特性,不利于推广;再次,编译期元编程的代码对初学者来说比较难理解,而应用起来更需要有较高的C++编程的火候;最后,我认为元类编程(以后如不加说明,均指运行时元类编程)其实是一种编程的思想和程序设计方法,它应当可以被应用于所有适合的场合。

其实,元类编程并不是C++的强项,标准C++的元语中就没有对元类的支持,这是由于元类编程的思想起源于元编程,而元编程的思想最初来自于lisp语言,它是一种解释性语言(linux 的大拿们可能会对这个语言有所了解),在最初的设计中,元编程主要是为了实现动态的生成或修改一个函数的行为,这个思想后来被引入到pythan、java 等现代解释性语言中,于是就产生了元类编程(或者叫面向方面编程),而它的直接目的就是希望通过在运行时修改或重组一个类的实现来达到一些传统编程方法无法达到的效果。而C++是一种编译性语言,其设计者自然更多的关注于一些编译期特性,然而这不代表我们不能使用这种(优秀的)语言来进行元类编程。

0 0
原创粉丝点击