zoukankan      html  css  js  c++  java
  • 名称的特殊处理(Name Mangling)

    先说一个事情, mangle 的意思是 vt.乱砍, 损坏; n. 碾压机。 这意味着 name mangling 就是要先把你精心想出的名字们碾碎, 再拼成独一无二的样子, 当然这么残忍的事情都是编译器瞒着你做的。
    一般而言, member 的名称前会被加上 class 名称, 形成独一无二的命名, 例如:

    class Bar(){public: int ival;};
    //其中的 ival 可能变成这样:
    //member 经过 name-mangling 后的结果之一
    ival__3Bar

    编译器你为何要这样? 请考虑这样的派生操作:

    class Foo: public Bar{public: int ival;};
    //所以必须 name-mangling 为:
    class Foo
    {
    public:
        int ival__3Bar;
        int ival__3Foo;
    };

    而对于函数, 因为 member function 可以被重载化, 所以需要更广泛的 magling 手法(更残酷的碾碎, 嗯嗯), 如:

    class Point
    {
    public:
        void (float newX);
        float x();
        ...
    };
    //转化为
    class Point
    {
    public:
        //这样能行?
        void x__5Point(float newX);
        float x__5Point();
        ...
    };

    函数如果这么转化, 会导致被重载化的函数实体拥有相同的名称, 为了让它们独一无二, 唯有再加上它们的参数链表(可以从参数原型得到)。 如果把参数类型也编码进去, 就一定可以制造出独一无二的效果, 使我们的 x() 函数有良好的转换(但如果你声明 extern "C" , 就会压抑 nonmember functions的 mangling 效果):

    class Point
    {
    public:
        void x__5PointFf(float newX);
        float x__5PointFv();
        ...
    };

    以上所示的只是 cfront 的编码方法, 目前的编译器并没有统一的编码方法。
    把参数和函数名称编码在一起, 编译器于是在不同的编译模块之间达成了一种有限的类型检验。 如:


    void print(const Point3d&){}


    但意外的被这样声明和调用:


    void print(const Point3d&);


    两个实体如果拥有独一无二的 name-mangling, 那么任何不不正确的调用操作在链接时期就因无法决议而失败。有时候我们把它称为 “确保类型安全的链接行为”。 我觉得这样很乐观, 因为它只可以捕捉函数的标记(或叫做函数签名, 就是指 函数名称 + 参数数目 + 参数类型)错误: 如果 “返回类型” 声明错误, 就没办法检查出来!
    在当前的编译系统中, 有一种所谓的 demangling 工具, 用来拦截名称并将其转换回去, 使用者仍然可以处于 “不知道类型名字的极大幸福之中”。
    因为 name-mangling 的手法残忍, 结果不堪, 所以一般不会给使用者看到。

  • 相关阅读:
    图论--曼哈顿距离最小生成树模板
    图论--生成树计数模板
    图论--欧拉回路--弗罗莱算法模板
    Codeforce 1255 Round #601 (Div. 2)D. Feeding Chicken (模拟)
    pta 习题集5-17 家谱处理
    pta习题集5-16 地下迷宫探索
    pta 习题集5-17 哥尼斯堡的“七桥问题”
    pta习题集5-16 朋友圈
    pta 习题集5-19 列车厢调度
    pta 习题集5-18 打印学生选课清单
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4115592.html
Copyright © 2011-2022 走看看