Для целей этого ответа я искал очень старую версию на gcc, потому что она меньше и проще рассуждать. Внедрение в новейших версиях или в других компиляторах может быть совершенно иным.
Источник файлы искали можно посмотреть на opensource.apple.com
НКУ имеет функцию is_friend()
, определенную в friend.c, который в основном возвращается, если функция или типа является другом. Вот соответствующий код функции:
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;
}
В основном, он получает список друзей определенного типа, и итерации через него, проверяя, если какое-либо из них равно функции тестируются. функция Friend добавлена к типу, используя аналогичные функции, определенные в том же исходном файле: add_friend()
, add_friends()
для всех функций-членов класса, make_friend_class()
для классов и т.д.
Я предполагаю, что он использует эту функцию, чтобы определить, , при проверке доступа (момент, когда он может кричать на вас для доступа к частному члену), если функция имеет доступ или нет.
Ответ на ваш вопрос (по крайней мере, для этой старой версии GCC): у компилятора есть список друзей для каждого класса и выполняется итерация этого списка, чтобы определить, является ли функция другом (во время компиляции, конечно.). Если это так, он просто предоставляет доступ. Для этого нет специального кода: это обычный вызов функции.
Нет ничего особенного в реализации функции друга во время выполнения. Это всего лишь механизм времени компиляции, позволяющий функции доступа к закрытым членам класса. –
Спасибо за комментарий. @JosephMansfield Я undrestand, что вы указываете, но механизм компиляции, который я пытаюсь понять. Можете ли вы поместить некоторую ссылку, чтобы я мог легко ссылаться. Поскольку я перечислил V-таблицу и V-ptr, также скопируйте изменение времени, но мы знаем, как происходит это изменение времени компиляции. – Nihar
Дополнительные вопросы: Не зависит от компилятора? Что говорит стандарт C++? – TobiMcNamobi