Почему я могу сделать дружественным класс, до которого определение ещё не дошло?

class Anything {
private:
    int m_count;
    friend class Temp;
public:
    Anything(int value = 0) : m_count(value) {};
};

class Temp {
private:
    int m_count;
public:
    Temp(int value = 0) : m_count(value) {};
};

Почему я могу сделать дружественным класс, до которого определение ещё не дошло. Как компилятор знает что существует класс Tempна этапе определение класса Anything?

А если сделать так, то это уже работать не будет, тк нужно объявить класс Temp в начале

class Anything {
private:
    int m_count;
    friend void out(const Anything& any, const Temp& temp);
public:
    Anything(int value = 0) : m_count(value) {};
};

class Temp {
private:
    int m_count;
    friend void out(const Anything& any, const Temp& temp);
public:
    Temp(int value = 0) : m_count(value) {};
};

Ответы (1 шт):

Автор решения: Mikhailo

Смотрите, в первом случае вы говорите

friend class Temp;

т.е. объясняете, что 1. Temp — это класс, и 2. что он друг. Пока что этого достаточно, компилятору не нужно знать внутренности этого класса, его размер и т.п.

Если же вы пишете

friend void out(const Anything& any, const Temp& temp);

то здесь говорится только, что вот такая функция с такими аргументами будет другом. Но что такое Temp? Может, это класс? Или, может, это просто алиас intа? а вдруг это еще какой тип? Ведь ничего не известно, что такое Temp! Вот поэтому в первом случае это работате как forward declaration, а во втором нет, потому что никакого forward declaration здесь нет.

→ Ссылка