friend函数是如何在内部实现的 在C++中,我们都使用了全局函数和类级的朋友函数。 我试图通过互联网搜索内部好友功能是如何实现的

friend函数是如何在内部实现的 在C++中,我们都使用了全局函数和类级的朋友函数。 我试图通过互联网搜索内部好友功能是如何实现的,c++,compiler-construction,friend-function,C++,Compiler Construction,Friend Function,“friend”关键字执行了哪些操作。 例如,我们知道v-ptr和v-table是如何在内部实现的,我正在寻找同样的答案 请注意: 这个问题与如何使用friend函数或friend函数的用法无关。为了回答这个问题,我在gcc上搜索了一个非常旧的版本,因为它更小,更容易推理。最新版本或其他编译器中的实现可能完全不同 可以在上查看搜索的源文件 gcc有一个函数is_friend(),在friend.c中定义,如果函数或类型是friend,它基本上会返回。以下是功能的相关代码: int is_frie

“friend”关键字执行了哪些操作。 例如,我们知道v-ptr和v-table是如何在内部实现的,我正在寻找同样的答案

请注意:
这个问题与如何使用friend函数或friend函数的用法无关。

为了回答这个问题,我在gcc上搜索了一个非常旧的版本,因为它更小,更容易推理。最新版本或其他编译器中的实现可能完全不同

可以在上查看搜索的源文件

gcc有一个函数
is_friend()
,在friend.c中定义,如果函数或类型是friend,它基本上会返回。以下是功能的相关代码:

int
is_friend (type, supplicant)
     tree type, supplicant;
{
  int declp;
  register tree list;
  tree context;

  if (supplicant == NULL_TREE || type == NULL_TREE)
    return 0;
/*
Comment added by me: The following defines are in tree.h
#define TREE_CODE(NODE) ((enum tree_code) (NODE)->common.code)
#define TREE_CODE_CLASS(CODE)    tree_code_type[(int) (CODE)]
This is expanded as:
declp = (tree_code_type[(int) (((enum tree_code) (supplicant)->common.code))] == 'd')
*/
declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
// That is, it will simply search the array for the code of the supplicant and check if it is a function declaration.

  if (declp)
    /* It's a function decl.  */
    {
      tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
      tree name = DECL_NAME (supplicant);
      tree ctype;

      if (DECL_FUNCTION_MEMBER_P (supplicant))
    ctype = DECL_CLASS_CONTEXT (supplicant);
      else
    ctype = NULL_TREE;

      for (; list ; list = TREE_CHAIN (list))
    {
      if (name == FRIEND_NAME (list))
        {
          tree friends = FRIEND_DECLS (list);
          for (; friends ; friends = TREE_CHAIN (friends))
        {
          if (same_type_p (ctype, TREE_PURPOSE (friends)))
            return 1;

          if (TREE_VALUE (friends) == NULL_TREE)
            continue;

          if (supplicant == TREE_VALUE (friends))
            return 1;

          /* With -fguiding-decls we are more lenient about
             friendship.  This is bogus in general since two
             specializations of a template with non-type
             template parameters may have the same type, but
             be different.  

             Temporarily, we are also more lenient to deal
             with nested friend functions, for which there can
             be more than one FUNCTION_DECL, despite being the
             same function.  When that's fixed, the
             FUNCTION_MEMBER_P bit can go.  */
          if ((flag_guiding_decls 
               || DECL_FUNCTION_MEMBER_P (supplicant))
              && same_type_p (TREE_TYPE (supplicant),
                      TREE_TYPE (TREE_VALUE (friends))))
            return 1;

          if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
              && is_specialization_of (supplicant, 
                           TREE_VALUE (friends)))
            return 1;
        }
          break;
        }
    }
    }
  else
    /* It's a type.  */
    {
    // ...
    }

  if (declp && DECL_FUNCTION_MEMBER_P (supplicant))
    context = DECL_CLASS_CONTEXT (supplicant);
  else if (! declp)
    /* Local classes have the same access as the enclosing function.  */
    context = hack_decl_function_context (TYPE_MAIN_DECL (supplicant));
  else
    context = NULL_TREE;

  /* A namespace is not friend to anybody. */
  if (context && TREE_CODE (context) == NAMESPACE_DECL)
    context = NULL_TREE;

  if (context)
    return is_friend (type, context);

  return 0;
}
基本上,它会获取特定类型的好友列表,并对其进行迭代,检查其中是否有任何好友与正在测试的函数相等。 通过使用相同源文件中定义的类似函数将友元函数添加到类型中:
add\u Friend()
add\u friends()
用于类的所有成员函数,
make\u friends\u class()
用于类等

我猜它使用这个函数来确定,当检查访问权限时(当它可能因为访问私人成员而对你大喊大叫的时候),该函数是否具有访问权限


您的问题的答案是(至少对于这个旧版本的GCC):编译器为每个类都有一个朋友列表,并迭代该列表以确定函数是否是朋友(当然是在编译时)。如果是,它只是授予访问权限。没有为此生成特殊代码:这是一个常规函数调用。

friend函数的运行时实现没有任何特殊之处。它只是一种编译时机制,允许函数访问类的私有成员。谢谢您的评论@JosephMansfield我没有重新定义您所指的内容,但我试图理解编译时机制。你能给我一些链接,让我可以很容易地参考。。正如我所列出的,V-table和V-ptr也有编译时修改,但我们知道comile时间修改是如何发生的。@Nihar不,虚拟函数是一种运行时机制。它会更改编译后的输出。正如您所说,可执行文件将创建v表等。
friend
函数不是这样的。它只会影响程序是否真正编译。如果您编写的程序有一个函数,并且编译该函数是否为
friend
,则添加
friend
关键字对编译后的输出没有影响。@Nihar很难知道如何回答这个问题。编译器只执行标准中关于
friend
关键字的规定。如何做到这一点取决于编译器。
friend
的任何实现细节都将与vtables的细节完全不同。这读起来像“我想知道沙子是如何使用的,就像我们如何使用公理来证明定理”——看起来很有意义,但前提是你不知道沙子、公理和定理是什么。任何类似于你的“喜欢”的答案都是一个巨大的延伸。我不知道你在问什么。