关于名称重整(name mangling)、多态性的一些简单介绍

时间:2022-03-24 11:52:42

在看GCC源码的时候看到mangles这个单词,于是google了一下。

在面向对象编程语言出现之前,如果你想要打印不同类型的数据,需要写多个方法,例如PrintInteger(int i),PrintString(string s) 和 PrintFloat(float f) 。也就是说, 你必须通过命名来区别行为和数据类型,因为OOP语言出现前任一语言,例如C,不允许你用相同的名字写方法, 即使他们的参数类型不同。

C++的来到实现了方法重载。因此,你可以写多个方法,例如PrintInteger(int i)、PrintString(string s) 和 PrintFloat(float f),编译器自会准确调用特定的Print方法。方法重载被一种称为名称重整(name mangling)的技术所支持,在这种技术中,编译器通过把原方法名称与其参数相结合产生一个独特的内部名字来取代原方法名称。 如此,当你调用Print(1)的时候, 编译器可能在内部用源于参数类型的前缀重命名Print方法,这样一来Print(1)可能就变成 i_Print (1) 。

下面是更详细的例子:

C++编译器实际上将下面这些重载函数:

voidprint(inti);

voidprint(charc);

voidprint(floatf);

voidprint(char* s);

编译为:

_print_int

_print_char

_print_float

_pirnt_string

这样的函数名,来唯一标识每个函数。注:不同的编译器实现可能不一样,但是都是利用这种机制。所以当连接是调用print(3)时,它会去查找_print_int(3)这样的函数。

下面说个题外话,正是因为这点,重载被认为不是多态,多态是运行时动态绑定(“一种接口多种实现”),如果硬要认为重载是多态,它顶多是编译时“多态”。

C++中的变量,编译也类似,如全局变量可能编译g_xx,类变量编译为c_xx等。连接是也是按照这种机制去查找相应的变量 。

方法重载仅是多态性的一种情形。 名称重整是一种支持方法重载的机制。更普遍的情况下,多态性是与继承相联系。 什么是继承呢?继承就是一个新类 (称为子类) 从被继承类(称为父类或超类)取得自身的部分定义同时增加一些自己的新的信息。 如果你在相同的类中重载方法,数据类型必须是不同的。如果你在继承关系下重载方法,子类与父类的方法可能完全相同,而且名称重整器生成同样的重整名称。

举例来说,假设一个超类定义一个Print(int i)方法而一个从它继承的子类也定义了一个Print(int i)方法。当你有一个子类的实例时,运用多态性调用Child.Print(int);而当你产生一个父类的实例时运用多态性调用 Parent.Print(int)。这就是继承多态性:相同的名字和签字但是类却不同。

继承多态性是通过使用一种与名称重整相关的另外一种机制实现的。编译器把方法 放置在一个被称为虚拟方法表(VMT)(其实是一个方法数组)的地方。每一个方法在VMT中都有一个索引, 如此当Print(int)被调用的时候,编译器将被路由到VMT处找寻Print方法和类的内在索引。这样一来,编译器就可以调用正确的方法实现。由编 译器负责管理所有的VMT索引和类偏移量。

简言之,多态性使你能够用非常相似的名字定义许多方法,这里的名字往往都是直观易记的。 OOP编译器自会根据调用者类理解到底该调用哪个方法。

有关name mangling的详细说明可以参考  http://en.wikipedia.org