Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.94
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 07:44     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #1
В заголовочном файле "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 недоступен. Что не так? Подскажите, пожалуйста.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.10.2011, 07:44     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса?
Посмотрите здесь:

Преобразование типа аргумента в тип класса и дружественная функция C++
Как исправить ошибку с перегруженным оператором C++
Как работает ссылка с объектами, классами и перегруженным оператором [] C++
C++ Указатель на объект с перегруженным оператором вывода(с наследованием)
C++ Шаблон класса и дружественная функция
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
bearwoolfs
 Аватар для bearwoolfs
15 / 15 / 2
Регистрация: 10.01.2011
Сообщений: 275
03.10.2011, 08:49     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #2
Рискну предположить, что переменная-член X не находиться в списке публичного доступа.
X доступна только в пределах своего класса и конструктора.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
03.10.2011, 09:28     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #3
alsav22, у тебя неверный прототип функции вывода:
C++
1
ostream& operator<<(ostream &t, const klass &b);
И реализация обычно такая:
C++
1
2
ostream& operator<<(ostream &t, const klass &b)
{ return (t << b.x); }
И еще скобочка закрывающая во втором тексте в конце имеется.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 10:11  [ТС]     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #4
Цитата Сообщение от 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".
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
03.10.2011, 10:38     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #5
Цитата Сообщение от alsav22 Посмотреть сообщение
Появляется ошибка, что член klass::x недоступен. Ещё, при попытке построения, синтаксическая ошибка: идентификатор "ostream".
Вот! А в файле с определением класса - есть инклуд iostream?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 11:20  [ТС]     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #6
Цитата Сообщение от 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 ==========
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
03.10.2011, 14:31     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #7
alsav22, инклуд iostream должен быть и в h-файле с интерфейсом класса, и в cpp-файле с реализацией методов.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
03.10.2011, 16:12     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #8
ValeryLaptev, Да можно и iosfwd
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.10.2011, 22:33  [ТС]     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #9
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
alsav22, инклуд iostream должен быть и в h-файле с интерфейсом класса, и в cpp-файле с реализацией методов.
Прошу прощения за занятое время, книгу невнимательно читаю. Ещё и using namespace std; надо включить в заголовочный.

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

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

ЗЫ Не компилировалось без using namespace std потому что без использования using нужно указывать квалификатор namespace явно, т.е. std::cout, std::string и т.д. или писать using std::cout и затем уже просто cout. Последнее тоже не советую делать в хедере.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
04.10.2011, 02:36  [ТС]     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #13
Цитата Сообщение от 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, а компилировать при этом я не пытался, считая, что если есть подчёркивание, то компиляция будет с ошибкой. Оказалось, что это не всегда так. Опыт приходит с годами. Благодарю за помощь!
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
04.10.2011, 09:36     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #14
alsav22, можно просто писать using std::cin;
using std::ostream;
Но без инклуда так не работает.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.10.2011, 10:10     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса?
Еще ссылки по теме:

Дружественная функция-оператор, доступ к закрытым полям класса C++
Дружественная функция не имеет доступа к приватным членам C++
C++ Дружественная функция класса

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

Или воспользуйтесь поиском по форуму:
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
04.10.2011, 10:10  [ТС]     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса? #15
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
alsav22, можно просто писать using std::cin;
using std::ostream;
Но без инклуда так не работает.
Это я знаю. Спасибо!
Yandex
Объявления
04.10.2011, 10:10     Почему дружественная функция с перегруженным оператором << не имеет доступа к данным класса?
Ответ Создать тему
Опции темы

Текущее время: 10:56. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru