今天闲来无事拿出Essential C++来看,看到构造函数一节看到Lippman大牛详详细细讲解了Constructor的各种用法。侯捷老师在翻译的时候还对部分Lippman漏讲的内容做了补充。于是围绕构造函数我写了下面几段代码,猜猜看输出会是什么?首先定义类:
明眼人一看就要说了,testClass的两个构造函数会产生歧义。恩是的,一般我们都会认为这段代码编译不过,然而……如果只是写个定义的话,却是可以编译过的。只有当我们在主程序里写上类似于。
这样的语句时,编译器(这里我用的G++)才会告诉你这一句的调用会产生歧义。由此我们可以发现编译器容许这样歧义的函数存在——只要他们不被调用。记得之前写dll的时候曾经用dependency看过生成好的dll里头C++函数的名字,这些函数的名字都被编译器加上了一串长长的尾巴,从而达到区分重载函数的目的。个人理解编译过程中是这样处理重载函数的:
1.对每个重载的函数进行名字破坏(也就是加上不同的尾巴)。
2.在解析代码过程中根据参数表决定调用的是哪个函数。
到这里我们便可以对前面观察到的现象做出解释了:在第2步中,编译过程中若没有遇到调用这些歧义函数的代码就不会报错,也不会发现存在这样歧义的函数。
最后,再思考下,如果这样写:
那么编译的时候会不会出错呢?若不出错,a.val的值是多少呢?
编译运行即可发现,编译不会报错,而a.val的值是3.这是因为(引用侯捷的译注)这时调用的事实上是一个参数的构造函数。从而在编译的第2步中成功地避免了歧义。