Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.58/40: Рейтинг темы: голосов - 40, средняя оценка - 4.58
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587

Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса?

03.10.2011, 07:44. Показов 8185. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В заголовочном файле "klass.h" есть класс:
C++
1
2
3
4
5
6
7
8
9
class klass
{
    int x;
public:
    klass();
    ~klass();
    void show();
    friend void operator<<(ostream& a, klass& b);
};
Когда в файле исходного кода (с олределениями функций) пытаюсь прописать определение дружественной функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "klass.h"
#include <iostream>
using namespace std;
 
klass::klass()
{
    x = 10;
}
klass::~klass()
{
}
void klass::show()
{
    cout << x << endl;
}
void operator<<(ostream& a, klass& b)
{
    a << b.x;
}
}
то вылазит ошибка, что член klass::x недоступен. Что не так? Подскажите, пожалуйста.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.10.2011, 07:44
Ответы с готовыми решениями:

Дружественная функция не имеет доступа к приватным членам
Добрый день. Возникла такая проблема: при обращении в теле дружественной функции класса к его приватному члену возникают ошибки &quot;...

Дружественная функция не может получить доступ к приватным данным класса
Доброго времени суток уважаемые форумчане), пытаюсь реализовать дружественную функцию которая берет данные из двух классов, но компилятор...

Почему дружественная функция не может обратиться к protected полю класса?
Не могу понять, почему функция не может обратиться к protected полю класса: class Ships { protected: int hits; int ships; ...

14
 Аватар для bearwoolfs
15 / 15 / 5
Регистрация: 10.01.2011
Сообщений: 275
03.10.2011, 08:49
Рискну предположить, что переменная-член X не находиться в списке публичного доступа.
X доступна только в пределах своего класса и конструктора.
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
03.10.2011, 09:28
alsav22, у тебя неверный прототип функции вывода:
C++
1
ostream& operator<<(ostream &t, const klass &b);
И реализация обычно такая:
C++
1
2
ostream& operator<<(ostream &t, const klass &b)
{ return (t << b.x); }
И еще скобочка закрывающая во втором тексте в конце имеется.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 10:11  [ТС]
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
alsav22, у тебя неверный прототип функции вывода:
C++
1
ostream& operator<<(ostream &t, const klass &b);
И реализация обычно такая:
C++
1
2
ostream& operator<<(ostream &t, const klass &b)
{ return (t << b.x); }
И еще скобочка закрывающая во втором тексте в конце имеется.
Скобочка только в сообщении. Переписал как вы советуете. Не помогло. Главное, с другими операторами всё нормально, но как только вставляю ostream& (возвращаемое значение или параметр), то сразу данные класса недоступны.
Например.
В классе такой прототип:
C++
1
friend void operator*(int a, klass& b);
В определениях пишу:
C++
1
2
3
4
5
6
void operator*(int a, klass& b)
{
 
    cout << a * b.x;
    
}
Всё нормально.
Но если так переписать:
C++
1
friend ostream& operator*(int a, klass& b);
C++
1
2
3
4
5
6
7
ostream& operator*(int a, klass& b)
{
 
    cout << a * b.x;
    return cout;
    
}
Появляется ошибка, что член klass::x недоступен. Ещё, при попытке построения, синтаксическая ошибка: идентификатор "ostream".
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
03.10.2011, 10:38
Цитата Сообщение от alsav22 Посмотреть сообщение
Появляется ошибка, что член klass::x недоступен. Ещё, при попытке построения, синтаксическая ошибка: идентификатор "ostream".
Вот! А в файле с определением класса - есть инклуд iostream?
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 11:20  [ТС]
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Вот! А в файле с определением класса - есть инклуд iostream?
Где определения методов класса? Есть. При построении следующий вывод:

1>------ Построение начато: проект: 1, Конфигурация: Debug Win32 ------
1> klass.cpp
1>d:\my c++projects\1\klass.h(10): error C2143: синтаксическая ошибка: отсутствие ";" перед "&"
1>d:\my c++projects\1\klass.h(10): error C2433: ostream: "friend" не разрешается для объявлений данных
1>d:\my c++projects\1\klass.h(10): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>d:\my c++projects\1\klass.h(10): error C2061: синтаксическая ошибка: идентификатор "ostream"
1>d:\my c++projects\1\klass.h(10): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>d:\my c++projects\1\klass.h(10): error C2805: бинарный "operator <<" имеет слишком мало параметров
1>d:\my c++projects\1\klass.cpp(20): error C2872: ostream: неоднозначный символ
1> может быть "d:\my c++projects\1\klass.h(10) : int ostream"
1> или "c:\program files (x86)\microsoft visual studio 10.0\vc\include\iosfwd(636) : std::ostream"
1>d:\my c++projects\1\klass.cpp(20): error C2143: синтаксическая ошибка: отсутствие ";" перед "&"
1>d:\my c++projects\1\klass.cpp(20): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>d:\my c++projects\1\klass.cpp(20): error C2086: int ostream: переопределение
1> d:\my c++projects\1\klass.h(10): см. объявление "ostream"
1>d:\my c++projects\1\klass.cpp(20): error C2872: ostream: неоднозначный символ
1> может быть "d:\my c++projects\1\klass.h(10) : int ostream"
1> или "c:\program files (x86)\microsoft visual studio 10.0\vc\include\iosfwd(636) : std::ostream"
1>d:\my c++projects\1\klass.cpp(20): error C2872: ostream: неоднозначный символ
1> может быть "d:\my c++projects\1\klass.h(10) : int ostream"
1> или "c:\program files (x86)\microsoft visual studio 10.0\vc\include\iosfwd(636) : std::ostream"
1>d:\my c++projects\1\klass.cpp(20): error C2065: a: необъявленный идентификатор
1>d:\my c++projects\1\klass.cpp(20): error C2059: синтаксическая ошибка: const
1>d:\my c++projects\1\klass.cpp(21): error C2143: синтаксическая ошибка: отсутствие ";" перед "{"
1>d:\my c++projects\1\klass.cpp(21): error C2447: {: отсутствует заголовок функции (возможно, используется формальный список старого типа)
1> Создание кода...
1> Компиляция...
1> 1.cpp
1> Создание кода...
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========

10) строчка это в объявлении класса: friend ostream& operator<<(ostream& a, const klass& b);

В файле с определениями:
20) ostream& operator<<(ostream& a, const klass& b)
21) {
22) return (a << b.x);
23) }

Добавлено через 15 минут
Если поместить определение вместо прототипа:
10) friend ostream& operator<<(ostream& a, const klass& b)
11) {
12) return (a << b.x);
13) }

, то ошибка с недоступностью x пропадает, а при построении вывод такой:

1>------ Построение начато: проект: 1, Конфигурация: Debug Win32 ------
1> klass.cpp
1>d:\my c++projects\1\klass.h(10): error C2143: синтаксическая ошибка: отсутствие ";" перед "&"
1>d:\my c++projects\1\klass.h(10): error C2433: ostream: "friend" не разрешается для объявлений данных
1>d:\my c++projects\1\klass.h(10): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>d:\my c++projects\1\klass.h(10): error C2061: синтаксическая ошибка: идентификатор "ostream"
1>d:\my c++projects\1\klass.h(11): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>d:\my c++projects\1\klass.h(11): error C2805: бинарный "operator <<" имеет слишком мало параметров
1>d:\my c++projects\1\klass.h(11): error C2333: klass::operator <<: ошибка в объявлении функции; пропуск основного текста функции
1> Создание кода...
1> Компиляция...
1> 1.cpp
1> Создание кода...
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
03.10.2011, 14:31
alsav22, инклуд iostream должен быть и в h-файле с интерфейсом класса, и в cpp-файле с реализацией методов.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
03.10.2011, 16:12
ValeryLaptev, Да можно и iosfwd
1
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 22:33  [ТС]
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
alsav22, инклуд iostream должен быть и в h-файле с интерфейсом класса, и в cpp-файле с реализацией методов.
Прошу прощения за занятое время, книгу невнимательно читаю. Ещё и using namespace std; надо включить в заголовочный.

Всем спасибо! И ещё раз извините за бестолковость.

Добавлено через 1 час 1 минуту
Сейчас поэкспериментировал с инклудами. Получается, что достаточно инклуды и using namespace std; прописать только в заголовочном файле, а в остальных файлах сделать инклуд заголовочного, и построение проходит без ошибок. И в книге так.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
03.10.2011, 23:09
alsav22, Ага. Только using namespace в хедере писать не стоит. Но это уже более высокие материи.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 23:40  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
alsav22, Ага. Только using namespace в хедере писать не стоит. Но это уже более высокие материи.
Может быть. Но, два факта. Во первых книга: Стивен Прата "Язык программирования С++. Лекции и упражнения. Учебник." Там using namespace std; пишется в хедере (скрин прилагаю). Во вторых, в том примере, где у меня возникла ошибка, если я пытался её исправить сделав #include <iostream> в заголовочном файле, то это ничего не давало (недоступность данных класса в реализации дружественной функции и при построении те же ошибки), а если я #include <iostream> не добавлял в h - файл, а прописывал в нём using namespace std;, то все ошибки исчезали.
Миниатюры
Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса?  
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
03.10.2011, 23:45
alsav22, Книга для новичков. Я ведь говорю это более высокие материи. Просто запомните, что в хедере так писать не стоит, а пока пишете учебные программы - пишите сколько хотите.

ЗЫ Не компилировалось без using namespace std потому что без использования using нужно указывать квалификатор namespace явно, т.е. std::cout, std::string и т.д. или писать using std::cout и затем уже просто cout. Последнее тоже не советую делать в хедере.
1
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
04.10.2011, 02:36  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
alsav22, Книга для новичков. Я ведь говорю это более высокие материи. Просто запомните, что в хедере так писать не стоит, а пока пишете учебные программы - пишите сколько хотите.

ЗЫ Не компилировалось без using namespace std потому что без использования using нужно указывать квалификатор namespace явно, т.е. std::cout, std::string и т.д. или писать using std::cout и затем уже просто cout. Последнее тоже не советую делать в хедере.
Согласен, что книга как раз для меня. А насчёт компиляции... Ведь когда возникала ошибка, using namespace std; отсутствовал только в хедер - файле, в котором не было ни cout, ни сin ... Такой был h-файл:
class klass
{
int x;
public:
klass();
~klass();
void show();
friend void operator<<(ostream& a, const klass& b);
};

Где тут, что явно указывать? А в остальных файлах using namespace std; присутствовал, а компиляциия, тем не менее, не проходила. Только после прописывания using namespace std; в хедер - файле ошибка исчезает.
Мне кажется, что всё это из за этого: ostream&. Если его нет, то компилируется и без
#include <iostream>, и без using namespace std; в хедер - файле.

Добавлено через 1 час 18 минут
Сейчас попробовал другим компилятором (Dev C++). То же самое. Пока не пропишу using namespace std; в h-файле, не компилируется. Выдаёт, в частности, это:
...
13 D:\Dev-Cpp\Dev-Cpp\klass.h ISO C++ forbids declaration of `ostream' with no type
13 D:\Dev-Cpp\Dev-Cpp\klass.h `ostream' is neither function nor member function; cannot be
13 D:\Dev-Cpp\Dev-Cpp\klass.h parse error before `&' token
...
После прописки, даже без #include <iostream> в h-файле, компилируется без ошибок.

Добавлено через 31 минуту
Нашёл, что можно явно указать в h-файле. Удалить из h-файла using namespace std; , а в прототипе функции явно указть: friend std::ostream& operator<<(std::ostream& ss, const klass& u); .
VC++ 2010 и Dev C++ компилируют без ошибок, НО, VC++ 2010, в файле реализации этой функции:
ostream& operator<<(ostream& ss, const klass& u)
{
ss << u.x;
return ss;
}
подчёркивает x, подсказка, что член класса недоступен (using namespace std; в этом файле прописан). С чего всё и началось. И, только если и тут явно указать std::ostream&, то подчёркивание исчезает.
Одним словом - заморочка.

Добавлено через 39 минут
А насчёт прописывания using namespace std; в заголовочном файле, я знаю, что это не желательно, потому что тогода эта директива будет присутствовать во всех файлах, а использование этой директивы не рекомендуется. Но в данном случае, когда в h-файле я пробовал указывать явно std::ostream& , в файле реализации этой функции не исчезало подчёркивание x, а компилировать при этом я не пытался, считая, что если есть подчёркивание, то компиляция будет с ошибкой. Оказалось, что это не всегда так. Опыт приходит с годами. Благодарю за помощь!
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
04.10.2011, 09:36
alsav22, можно просто писать using std::cin;
using std::ostream;
Но без инклуда так не работает.
1
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
04.10.2011, 10:10  [ТС]
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
alsav22, можно просто писать using std::cin;
using std::ostream;
Но без инклуда так не работает.
Это я знаю. Спасибо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.10.2011, 10:10
Помогаю со студенческими работами здесь

Дружественная функция класса
Проблема в том что дружественная функция класа механик в класе car (friend void update_status) не может обращатся к полям, почему? ...

Класс с перегруженным оператором присваивания
Добрый день, задали в университете написать класс с перегрузкой оператора присваивания, с использованием динамического массива. Я только...

Шаблон класса и дружественная функция
Доброго времени суток. Столкнулся с непониманием одного процесса. Задача звучит следующим образом: Написать шаблон функции isEqualTo для...

Как исправить ошибку с перегруженным оператором
Добрый вечер! суть задания: Необходимо реализовать класс, который умеет хранить данные произвольных типов (int, char, любой другой объект...

Дружественная шаблонная функция шаблонного класса
Не компилируется. Подскажите правильный синтаксис. template&lt;typename T&gt; class A; template&lt;typename T, typename ... Args&gt; void...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит: токи, напряжения и их 1 и 2 производные при t = 0;. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru