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; } }
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Делаю обертку вокруг winapi окна, нужно затащить wndproc в класс а он статическийВобщем WindowProc не работает почемуто
Нужно подключить любую СУБД к проекту Netbeans (C++, MinGW)Провёл день в попытках подключить MySQL, так и не найдя нигде инструкции или документации
Почему у функции scanf_s в Visual Studio 2013 при использовании "%s" прекращается работа в языке Си