代码之家  ›  专栏  ›  技术社区  ›  Stefano Borini

什么是名称管理,它是如何工作的?

  •  39
  • Stefano Borini  · 技术社区  · 16 年前

    请解释什么是名称管理,它是如何工作的,它解决了什么问题,以及在什么上下文和语言中使用。名称管理策略(例如编译器选择的名称和原因)是一个加号。

    10 回复  |  直到 7 年前
        1
  •  35
  •   Norman Ramsey    16 年前

    在您选择的编程语言中,如果标识符是从单独编译的单元导出的,它需要一个在链接时已知的名称。名字命名 解决了标识符过载的问题 在编程语言中。(如果同一名称在多个上下文中使用或具有多个含义,则标识符将被“重载”。)

    一些例子:

    • 在C++中,函数或方法 get 可能在多个类型上重载。

    • 在ADA或模-3中,函数 得到 可能出现在多个模块中。

    多种类型和多个模块涵盖了通常的上下文。

    典型策略:

    • 将每个类型映射到一个字符串,并使用组合的高级标识符和“类型字符串”作为链接时间名称。C++中常见(特别是因为只允许对函数/方法进行重载,并且只在参数类型上)和艾达(在这里也可以重载结果类型)。

    • 如果标识符在多个模块或命名空间中使用,请将该模块的名称与标识符的名称连接起来,例如, List_get 而不是 List.get .

    根据链接时间名称中哪些字符是合法的,您可能需要进行额外的管理;例如,可能需要使用下划线作为“转义”字符,以便您可以区分

    • List_my.get -gt; List__my_get

    • List.my_get -gt; List_my__get

    (不可否认,这个例子正在实现,但是作为一个编译器编写者,我必须保证 源代码中的不同标识符映射到不同的链接时间名称 . 这就是名字乱写的全部原因和目的。)

        2
  •  24
  •   Andrew Hare    16 年前

    简单地说,名称管理是一个编译器通过更改源代码中标识符的名称来帮助 linker 在这些标识符之间消除歧义。

    Wikipedia has a wonderful article on this subject 举几个很好的例子。

        3
  •  4
  •   Reed Copsey    16 年前

    Name mangling 是编译器修改对象的“已编译”名称,使其与以一致方式指定的名称不同的方法。

    这使得编程语言能够灵活地为多个已编译的对象提供相同的名称,并具有查找适当对象的一致方法。例如,这允许多个具有相同名称的类存在于不同的命名空间中(通常通过将命名空间前置到类名中,等等)。

    许多语言中的运算符和方法重载使这一点更进一步——每个方法在编译的库中都以一个“损坏的”名称结束,以便允许一个类型上的多个方法以相同的名称存在。

        4
  •  2
  •   John Fouhy    16 年前

    在Python中,名称管理是一个系统,通过它类变量在类内和类外具有不同的名称。程序员通过在变量名的开头加上两个下划线来“激活”它。

    例如,我可以用一些成员定义一个简单的类:

    >>> class Foo(object):
    ...  def __init__(self):
    ...   self.x = 3
    ...   self._y = 4
    ...   self.__z = 5
    ... 
    

    在Python实践中,以下划线开头的变量名是“内部”的,而不是类接口的一部分,因此程序员不应该依赖它。但是,它仍然可见:

    >>> f = Foo()
    >>> f.x
    3
    >>> f._y
    4
    

    以两个下划线开头的变量名仍然是公共的,但名称已损坏,因此很难访问:

    >>> f.__z  
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Foo' object has no attribute '__z'
    

    但是,如果我们知道Mangling这个名字是如何工作的,我们就可以得到它:

    >>> f._Foo__z
    5
    

    也就是说,类名在变量名前面加了一个下划线。

    python没有“private”和“public”成员的概念;一切都是公共的。名称管理是程序员可以发送的最强烈的信号,即不应该从类外部访问变量。

        5
  •  2
  •   Santosh    11 年前

    来源: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

    名称Mungle是C++编译器使用的过程,给程序中的每个函数赋予唯一的名称。在C++中,程序通常至少有几个具有相同名称的函数。因此,名字模糊可以被认为是C++中的一个重要方面。

    例子: 通常,成员名称是通过将成员的名称与类的名称串联而唯一生成的,例如给定声明:

    class Class1
     {
            public:
                int val;
                ...
      };
    

    Val变成了:

      // a possible member name mangling
         val__11Class1
    
        6
  •  0
  •   Stefano Borini    16 年前

    在Fortran中,由于语言不区分大小写,因此需要进行名称管理,这意味着foo、foo、foo、foo等。将全部解析为相同的符号,其名称必须以某种方式规范化。不同的编译器实现的管理方式不同,这在与使用不同编译器编译的C或二进制对象进行接口时是一个很大的问题。例如,gnu g77/g95总是在较低的名称中添加一个尾随下划线,除非名称已经包含一个或多个下划线。在这种情况下,将添加两个下划线。

    例如,以下例程

        program test
        end program 
    
        subroutine foo()
        end subroutine
    
        subroutine b_ar()
        end subroutine
        subroutine b_a_r()
        end subroutine
    

    生成以下损坏的符号:

    0000000000400806 g     F .text  0000000000000006              b_ar__
    0000000000400800 g     F .text  0000000000000006              foo_
    000000000040080c g     F .text  0000000000000006              b_a_r__
    

    为了从C中调用Fortran代码,必须调用正确损坏的例程名(显然要考虑到真正独立于编译器的可能不同的管理策略)。要从Fortran调用C代码,C-written接口必须导出正确损坏的名称并将调用转发到C例程。然后可以从Fortran调用此接口。

        7
  •  0
  •   Ajay yadav    10 年前

    大多数面向对象语言都提供了函数重载特性。 函数得载 如果任何类有多个同名但参数类型和编号不同的函数,则称它们被重载。函数重载允许您对不同的函数使用相同的名称。

    函数过载的方法

    1. 通过更改参数的数目。
    2. 通过具有不同类型的参数列出项。

    如何通过名称管理实现函数重载?
    C++编译器在生成目标代码时区分不同的函数,它通过根据参数的类型和数量添加关于参数的信息来改变名称。这种向表单函数名添加附加信息的技术称为名称管理。 C++标准没有指定任何特定的名称修改技术,因此不同的编译器可能会将不同的信息附加到函数名。 我已经在GCC4.8.4上运行了示例程序。

    class ABC
    {       
     public:
      void fun(long a, long b) {}
      void fun(float a, float b) {} 
      void fun(int a, float b) {}   
    };
    int main()
    {
     ABC obj;
     obj.fun(1l,2l);
     obj.fun(1,2.3f);
     obj.fun(3.2f,4.2f);
     return 0;
    }
    

    这个程序有3个函数,命名为fun-with,根据参数数量和类型的不同而有所不同。 这些函数名的管理方式如下:

    ayadav@gateway1:~$ nm ./a.out |grep fun
    000000000040058c W _ZN3ABC3funEff
    00000000004005a0 W _ZN3ABC3funEif
    000000000040057a W _ZN3ABC3funEll
    
    • abc是类名称的命令字符串
    • fun是函数名的常用字符串
    • FF双浮点->f参数类型
    • l l两个long->l类型的参数
    • 如果第一个整数参数->i和一个浮点->f参数
        8
  •  0
  •   Sam Hobbs    8 年前

    在设计链接编辑器时,C、Fortan和COBOL等语言没有名称空间、类、类成员和其他内容。需要名称管理来支持面向对象的特性,例如那些带有不支持它们的链接编辑器的特性。链接编辑器不支持附加功能这一事实经常被忽略;人们通过说由于链接编辑器的原因,需要进行名称管理来暗示这一点。

    由于支持名称管理的语言需求之间存在很大差异,因此在链接编辑器中如何支持名称管理的问题没有一个简单的解决方案。链接编辑器设计用于处理来自各种编译器的输出(对象模块),因此必须具有支持名称的通用方法。

        9
  •  0
  •   grepit    7 年前

    前面的所有答案都是正确的,但下面是Python透视图/示例推理。

    定义

    当一个类中的变量的前缀为uuuu(即两个下划线)&时,它没有后缀为uuu(即两个或更多下划线),则被视为私有标识符。 python解释器转换任何私有标识符,并将名称管理为\u类\u标识符

    Example:
    MyClassName --> _myClassName
    __variable --> __variable
    

    为什么?

    这是必需的,因为要避免由重写属性引起的问题。换句话说,为了重写,python解释器必须能够为子方法和父方法构建不同的ID,并且使用uuuu(双下划线)使python能够做到这一点。在下面的示例中,如果没有\帮助,此代码将无法工作。

    class Parent:
        def __init__(self):
           self.__help("will take child to school")
        def help(self, activities):
            print("parent",activities)
    
        __help = help   # private copy of original help() method
    
    class Child(Parent):
        def help(self, activities, days):   # notice this has 3 arguments and overrides the Parent.help()
            self.activities = activities
            self.days = days
            print ("child will do",self.activities, self.days)
    
    
    # the goal was to extend and override the Parent class to list the child activities too
    print ("list parent & child responsibilities")
    c = Child()
    c.help("laundry","Saturdays")
    
        10
  •  0
  •   zerocool    7 年前

    这里的答案太棒了,所以这只是我小经验中的一个补充:我使用名称管理来了解,什么工具(gcc/vs/…)以及参数是如何传递到堆栈的,以及我正在处理的调用约定,以及基于名称的,例如,如果看到 _main 我知道这是一个 Cdecl 其他人也一样

    推荐文章