file.cpp
#include "file.h"
namespace NS
{
void f(const A &obj)
{
std::cout << obj.data;
}
}
file.h
class A
{
private: int data;
friend void NS::f(const A &obj);
}
Компилятор на это ругается. Если описать NS в file.cpp до class A, то все работает. Подскажите, пожалуйста, чего я не понимаю? Почему так происходит? Как сделать так, чтобы работало, когда NS в другом файле?
UPD: и в одном файле не работает. "Использование неопределенного типа А"
Исправляется это так:
file.cpp остается без изменений.
В file.h пишется вот что:
class A;
namespace NS
{
void f(const A &obj);
}
class A
{
private:
int data;
friend void NS::f(const A &obj);
}
Почему ваш вариант не работал?
Во-первых, компилятору не было известно, что такое NS: пространство имен или класс, или еще что-то.
Однако даже если добавить над классом namespace NS {}, работать все равно не будет, но в этот раз ошибка будет другая: error: 'void NS::f(const A&)' should have been declared inside 'NS' (c) GCC.
Будь f в том же пространстве имен, что и класс, friend void f(const A &); сработало бы без объявления функции. (Эта строчка сама была бы объявлением функции, хотя до нормального (пере)объявления ее можно было бы достать только через argument-dependent lookup.)
Почему так? Видимо разработчики стандарта решили, что объявлять функции в произвольных пространствах имен из классов в других пространствах имен - это перебор.
В языке С++ квалифицированные имена, вроде NS::f, используются только для ссылки на уже ранее объявленные, т.е. уже известные компилятору сущности. Хотите использовать квалифицированное имя - позаботьтесь о том, чтобы сущность, на которую это имя ссылается, была объявлена заранее. Упрощенно выражаясь, такие сущности должны быть объявлены выше по файлу.
Использовать дружбу с функцией можно, если только объявлена эта функцию заблаговременно. Объявлять функцию можно, но заблаговременно нужно объявить класс. Неважно в каком файле вы это будете делать, главное порядок.
# include <iostream>
class A;
namespace NS{
void f(const A &obj); }
class A
{
private: int data;
friend void NS::f(const A &obj);
};
namespace NS {
void f(const A &obj) {
std::cout << obj.data; } }
Сборка персонального компьютера от Artline: умный выбор для современных пользователей