Определение функции друга внутри объявления класса - PullRequest
0 голосов
/ 23 апреля 2020

Я обнаружил, что функция Friend может быть определена внутри объявления класса. Я немного сбит с толку из-за того, что это означает, потому что объявление класса не предоставляет его тело, в общем случае это просто class A;.

Функции друзей могут быть определены (учитывая тело функции) внутри объявления класса. Эти функции являются встроенными функциями, и, подобно встроенным функциям-членам, они ведут себя так, как если бы они были определены сразу после того, как все члены класса были просмотрены, но до закрытия области действия класса (конец объявления класса). Функции-друзья, которые определены внутри объявлений класса, находятся в области действия включающего класса.

Источник: https://docs.microsoft.com/en-us/cpp/cpp/friend-cpp?view=vs-2019

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

Объявление класса может быть одновременно определением класса.

Вы не можете поместить определение функции друга в класс, который не определяется.

Учтите, что если такая функция друга не объявлена ​​вне класса, предоставляющего дружбу, то она невидим Он может быть найден только с помощью поиска имени в зависимости от аргумента.

Вот демонстрационная программа.

#include <iostream>

class A
{
private:
    int x;

public:
    A( int x ) : x ( x ) {}
    operator int() const { return x; }
    friend void f( const A &a )
    {
        std::cout << "a.x = " << a.x << '\n';
    }
};

void f( int x )
{
    std::cout << "x = " << x << '\n';
}

int main() 
{
    f( A( 10 ) );
    ( f )( A( 20 ) );

    return 0;
}

Вывод программы:

a.x = 10
x = 20

В этом вызове

f( A( 10 ) );

имя функции друга найдено из-за зависимого от аргумента поиска.

В этом вызове

( f )( A( 20 ) );

, заключив имя функции в скобки, отключает поиск, зависящий от аргумента, и вызывается функция, не являющаяся другом.

Или вы можете использовать квалифицированное имя функции, например

::f( A( 20 ) );

В этом случае ADL также не будет работать, и функция друга будет вызвана.

Также имейте в виду, что функция друга, определенная в классе, находится в лексической области видимости класса. Это означает, что он может использовать имена членов класса. Функция Friend, определенная вне класса, не входит в лексическую область класса.

0 голосов
/ 23 апреля 2020

Это означает, что

class A
{
public:
    friend std::ostream& operator << (std::ostream& os, const A&a)
    {
        return os << a.m1 << a.m2;
    }
};

эквивалентно

class A
{
public:
    friend std::ostream& operator << (std::ostream& os, const A&a);
};

inline std::ostream& operator << (std::ostream& os, const A&a)
{
    return os << a.m1 << a.m2;
}
...