C++/CLI基本数据类型探索(2)
在iso-c++中,这将被辨析为第3个foo(),因为字符串字面常量更接近const char*,而非iso-c++标准库中的string类型。但是,在c++/cli中,上面的调用将被辨析为第1个foo(),因为现在字符串字面常量被认为更接近system::string,而非字符指针。要理解其中的缘由,让我们往后退两步,先来看看iso-c++和c++/cli如何辨析一个重载函数,然后再来看iso-c++和c++/cli如何辨析一个字符串字面常量。
一个重载函数的辨析过程通常包含以下三个步骤:
1.选择候选函数集合。候选函数是指那些从词法范畴来看与所调用函数名相匹配的函数。例如,由于我们上面是在r的一个实例上调用foo(),所以所有名称为foo但却不是r或者其基类的成员的那些函数将不被认为是候选函数。这样看来,我们现在有三个候选函数,即r中三个名称为foo的成员函数。如果这个阶段得到的候选函数集合为空,那么调用将告失败。
2.从候选函数集合中选择可用函数集合。可用函数是指函数声明时的参数个数和它们的类型与调用时所指定的相匹配的那些函数。在我们上面的例子中,三个候选函数都是可用函数。如果这个阶段得到的可用函数集合为空,那么调用也将失败。
3.从可用函数集合中选择最匹配的函数。这个阶段将会对实际传递的参数和可用函数所声明的参数之间的转换进行一个排名。对于只含一个参数的函数来说,这个过程比较简单。但是对于含有多个参数的函数来说,这个过程就变得相对有些复杂。如果没有一个最佳的匹配函数胜出,那么调用将告失败。也就是说各个可用函数的参数类型到实际参数类型之间的转换被认为一样的好,换言之多个调用之间产生了混淆。
那么现在摆在我们面前有两个问题:(1)我们实际传递的参数"pooh"到底是什么类型?(2)在判定类型转换的优劣时采用的是什么算法?
在iso-c++中,字符串字面常量"pooh"的类型为const char[5]――注意,在字符串字面常量后面有一个隐含的截断字符null。在上面的例子中显然不存在这样的精确匹配,因此必须应用某种形式的类型转换。这样,两个iso-c++候选函数(2)和(3)将进行竞争:
void foo( std::string ); // (2)
void foo( const char* ); // (3)
那么编译器如何从中判断可用函数呢?c++语言对类型转换按照优先顺序定义有一个层级结构,在这个结构中,如果一种转换优于另一种转换,那么它将被排在前面。在c++/cli中,我们将cli类型的行为也集成到了iso-c++的标准类型转换层级结构中。下面是对集成之后的层级结构的一个描述:
1)精确匹配是最好的。需要注意的是精确匹配并不意味着实际传递的参数类型和函数声明的形式参数类型完全匹配。它们只需要“足够接近”就可以了。我们下面将会看到,“足够接近”对于iso-c++和c++/cli中的字符串字面常量有着一些不同的含义。
2)在标准转换中,拓宽转换要优于非拓宽转换。例如,将short拓宽为int要优于将int转换为double。
3)标准转换优于装箱(boxing)转换。例如,将int转换为double优于将int装箱为object。
4)装箱转换优于用户自定义的隐式转换。
5)用户自定义的隐式转换优于没有任何转换!
6)否则,用户必须使用显式的转型符号来表示期望的转换。
对于上面两个iso-c++下的候选函数,将字符串字面常量转换为一个std::string属于上面第5条,即隐式调用string的构造器来创建一个临时string对象。而将字符串字面常量转换为一个const char* 属于上面第1条。第1条优于第5条,因此,参数为const char*的那个函数在这场竞争中胜出。
这种归属在第1条“精确匹配”下的trivial conversions实际上在技术的定义上是很严格的。总共有4种这样的trivial conversions可以被归为精确匹配。即使在这4种trivial conversions中,为了规范语言对类型的选择,它们也有一个优先级的排序。
大多数读者和程序员可能对于这样的细节没有多大兴趣,并且通常情况下我们也无须深入到这些细节的地方。但是如果我们要得到一个直观的语言行为、并且确保它们在不同的实现上表现相同,这些规则的存在就很有必要。这是因为作为一门编程语言,它的行为一般要具有某种程度的“类型感知”能力,从而允许程序员忽略这些细节。 下面让我们来对这4种trivial conversions做一简单的了解。其中3种被称为左值转换(lvalue transformation)。左值(lvalue)是一个可寻址的,可被执行写操作的程序实体。第4种为限定性转换(qualification conversion),例如,在一个类型声明上加一个const修饰符就属于这种转换。其中3种左值转换优于限定性转换。
在我们上面的例子中,由本地数组到指针的转换,即由const char [5]到const char *,就是一种左值转换。在大多数情况下,我们甚至不将这看作一种转换。
这种形式的左值转换在c++/cli中仍然适用,但是在我们将system::string类引入之后,字符串字面常量到const char*的转换就不再是最好的匹配了。实际上,在c++/cli中,"pooh"这样的字符串字面常量的类型既是const char[5
Tag: CLI
文章整理:iocblog
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。