Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
 Аватар для ELchemist
2 / 2 / 0
Регистрация: 14.03.2018
Сообщений: 51

Как правильно передать указатель this в сторонний класс?

09.11.2018, 09:20. Показов 1767. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот файлы:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Field.cpp
 
#include "Field.hpp"
 
Field::Field(void) {
    attacked = 0;
    is_free = true;
}
 
StatusBool Field::get_if_attacked(void) const {
    return attacked;
}
void Field::inc_attacked(void) {
    attacked++;
}
void Field::dec_attacked(void) {
    if (!attacked) throw EPField("The parameter \"attacked\" can\'t be less than zero", this);
    attacked--;
}
 
StatusBool Field::get_if_free(void) const {
    return is_free;
}
void Field::release_field(void) {
    if (is_free == true) throw EPField("The field is already free", this);
    is_free = true;
}
void Field::take_field(void) {
    if (is_free == false) throw EPField("The field is already taken", this);
    is_free = false;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// EPField.hpp
 
#ifndef EPFIELD_HPP
#define EPFIELD_HPP
 
#include "ErrorProcessing.hpp"
#include "Field.hpp"
 
class EPField : public ErrorProcessing {
    public:
        EPField(ErrorText ex_error_text, Field *ex_error_field);
 
    private:
        Field *error_field;
 
        void print_variables() const;
};
 
#endif // EPFIELD_HPP
C++
1
2
3
4
5
6
7
8
9
10
11
12
// EPField.cpp
 
#include "EPField.hpp"
 
EPField::EPField(ErrorText ex_error_text, Field *ex_error_field)
: ErrorProcessing(ex_error_text), error_field(ex_error_field) {}
 
void EPField::print_variables() const {
    std::cout << "Variables:" << std::endl
              << "attacked = " << error_field->attacked << std::endl
              << "is_free = " << error_field->is_free << std::endl;
}
И еще (на всякий случай) :

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ErrorProcessing.hpp
 
#include <string>
#include <iostream>
#include <cstdlib>
 
#ifndef ERRORPROCESSING_HPP
#define ERRORPROCESSING_HPP
 
typedef std::string ErrorText;
 
class ErrorProcessing {
    public:
        ErrorProcessing(ErrorText ex_error_text);
        virtual ~ErrorProcessing();
 
        void print_report() const;
 
    private:
        ErrorText error_text;
 
        virtual void print_variables() const;
        void print_error_text() const;
};
 
#endif // ERRORPROCESSING_HPP
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ErrorProcessing.cpp
 
#include "ErrorProcessing.hpp"
 
using std::cout;
using std::endl;
 
ErrorProcessing::ErrorProcessing(ErrorText ex_error_text)
: error_text(ex_error_text) {
    cout << endl << "***ERROR DETECTED!!!***" << endl;
}
ErrorProcessing::~ErrorProcessing(void) {
    cout << "Press enter to exit..." << endl;
    std::cin.get();
    exit(1);
}
 
void ErrorProcessing::print_report() const {
    cout << endl;
    print_error_text();
    cout << endl;
    print_variables();
    cout << endl;
}
 
void ErrorProcessing::print_variables(void) const {
    cout << "Variables:" << endl
         << "<NO VARIABLES>" << endl;
}
void ErrorProcessing::print_error_text(void) const {
    cout << "Error: " << error_text << endl;
}
Не могу скомпилировать. Может я неправильно передал указатель this? Вот лог из Code::Blocks
Code
1
2
3
4
|| === Build: Debug in 8Queens (compiler: GNU GCC Compiler) === |
include\EPField.hpp |9| error: 'Field' has not been declared |
include\EPField.hpp |12| error: 'Field' does not name a type |
|| === Build finished: 2 error(s), 0 warning(s) (0 minute(s), 2 second(s)) === |
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.11.2018, 09:20
Ответы с готовыми решениями:

Как правильно передать указатель на структуру, и правильно ее использовать
Я планирую сделать сортировку, но компилятор начал ругаться &quot;Нет существует подходящей функции преобразования &quot;Student&quot; в...

Не знаю как правильно передать указатель
В общем для начала приложу код ( не пугайтесь , что придется много читать , из этого кода изучить нужно лишь 2 функции и данные структуры )...

Как правильно передать массив через указатель?
#pragma once #include &lt;vector&gt; class TOMathModel { public: TOMathModel(void); ~TOMathModel(void);

10
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
09.11.2018, 09:48
ELchemist, а есть сам класс Field?
0
4 / 2 / 2
Регистрация: 11.02.2018
Сообщений: 24
09.11.2018, 10:59
Кстати, да. А где сам класс Field?

Добавлено через 6 минут
Кстати, советую использовать :
C++
1
#pragma once
Вместо:
C++
1
2
3
#ifndef ...
#define ...
#endif
Если конечно, у вас не старый компилятор(или есть серьезные причины это не использовать). Так как проще и быстрее. Ещё и скорость компиляции возврастает.

Добавлено через 11 минут
Я так понял конструктор класса EPField должен получить текст ошибки и указатель на Field, но в данном случае компилятор ругается, что не объявлен класс Field. Указатель this ту не причем, ошибка только в том, что компилятор не видит Field.hpp(точнее объявление класса Field)

Добавлено через 56 секунд
Выложите field.hpp, так как его не хватает для полной картины.
1
 Аватар для ELchemist
2 / 2 / 0
Регистрация: 14.03.2018
Сообщений: 51
09.11.2018, 15:12  [ТС]
Вот файл по заявкам

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Field.hpp
 
#ifndef FIELD_HPP
#define FIELD_HPP
 
#include "EPField.hpp"
 
typedef bool StatusBool;
 
class Field {
    public:
        Field();
 
        StatusBool get_if_attacked() const;
        void inc_attacked();
        void dec_attacked();
 
        StatusBool get_if_free() const;
        void release_field();
        void take_field();
 
    private:
        unsigned int attacked;
        StatusBool is_free;
 
        friend class EPField;
};
 
#endif // FIELD_HPP
Добавлено через 3 минуты
Цитата Сообщение от emik_g777 Посмотреть сообщение
Кстати, советую использовать :
C++
1
#pragma once
Вместо:
C++
1
2
3
#ifndef ...
#define ...
#endif
Я знал об этом. Просто в Code::Blocks я пользовался конструктором классов. Вот он так и генерировал. Но, все равно, спасибо за совет

Добавлено через 13 минут
Цитата Сообщение от emik_g777 Посмотреть сообщение
Я так понял конструктор класса EPField должен получить текст ошибки и указатель на Field, но в данном случае компилятор ругается, что не объявлен класс Field. Указатель this ту не причем, ошибка только в том, что компилятор не видит Field.hpp(точнее объявление класса Field)
Вы правильно поняли принцип класса EPfield, но неправильно поняли ошибку. Я не выложил Field.hpp с самого начала, потому что думал, что здесь он не причем.
Этот класс работает, если нет никаких упоминаний о Field.
Мне кажется, что эти два класса надо разместить в одном файле, поскольку у них связь обоюдная.
0
4 / 2 / 2
Регистрация: 11.02.2018
Сообщений: 24
09.11.2018, 17:17
Лучший ответ Сообщение было отмечено ELchemist как решение

Решение

Простите, я что-то затупил(как говорится в просто народе). сейчас понял в чем ошибка. Вы должны понимать как работает препроцессор. Представьте как происходит:
Предположим(в данном случае так и есть, но в другом компиляторе может выйти ошибка, что не объявлен класс EPField)
Препроцессор
C++
1
#include "..."
Говорит компилятору, надо вставить код файла "..." перед компиляцией. Предположим В главной ветке(Где есть main(Ну или главный файл cpp)). Стоит
C++
1
#include "Field.hpp"
Там он вставляет перед кодом код файла "Field.hpp", естественно, с директивой
C++
1
#include "EPField.hpp"
И когда он вставляет код,получается что-то следующее
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class EPField : public ErrorProcessing {
    public:
        EPField(ErrorText ex_error_text, Field *ex_error_field);
        ...
};
 
 
class Field {
    public:
        Field();
        ...
 
        friend class EPField;
};
Я пишу упрощенно, чтобы было понятно. Понятное дело компилятор не может понять, что объявлен класс Field, ведь он объявлен уже после использования.

Добавлено через 24 минуты
Цитата Сообщение от emik_g777 Посмотреть сообщение
Представьте как происходит:
Предположим(в данном случае так и есть, но в другом компиляторе может выйти ошибка, что не объявлен класс EPField)
Простите, сейчас понял, что глупость написал, от компилятора это не зависит, только от того, в какой последовательности пишут директиву
C++
1
#include
Цитата Сообщение от emik_g777 Посмотреть сообщение
Там он вставляет перед кодом код файла "Field.hpp", естественно, с директивой
А вот это уже правильно. Для упрощения понимания, чуть подробнее распишу(тут не главное main и то, что может не быть #include "Field.hpp", он может быть вложен в другой файл, просто для упрощения так пишу. Будем считать, что с файла, где находится main будет всегда начинаться компиляция(опять для упрощения понимания)):

C++
1
2
3
4
5
6
7
#include "Field.hpp"
 
 
int main() {
...
return 0;
}
Он это превратит в:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "EPField.hpp"
 
class Field {
    public:
        Field();
        ...
 
        friend class EPField;
};
 
int main() {
...
return 0;
}
А после в :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class EPField : public ErrorProcessing {
    public:
        EPField(ErrorText ex_error_text, Field *ex_error_field);
        ...
};
 
 
class Field {
    public:
        Field();
        ...
 
        friend class EPField;
};
 
int main() {
...
return 0;
}
Надеюсь вы понимаете, зачем нужны конструкции:
C++
1
2
3
#ifndef ...
#define ...
#endif
Именно благодаря им не происходит зацикливание и переопределение.

На строке
C++
1
EPField(ErrorText ex_error_text, Field *ex_error_field);
Компилятор по логике должен знать класс Field, но он ещё не был объявлен, поэтому ничего не получится(Тут не важно ссылка это или сам объект).
Так что надеюсь вы все поняли.

Добавлено через 5 минут
Когда-то читал, что можно объявить класс, а после его определить, вроде так:
class Field;
Но можно использовать только ссылки и указатели на него. Я читал об этом, но никогда не приминал к этому(всегда старался избегать подобных конфликтов, как у вас, поэтому не пользовался этой возможностью), так что не знаю, получиться ли воспользоваться этим. По сути это вроде как прототип функции. Но пять-таки я этим не пользовался, если у вас получиться отпишитесь.
1
 Аватар для ELchemist
2 / 2 / 0
Регистрация: 14.03.2018
Сообщений: 51
10.11.2018, 11:54  [ТС]
Ваше решение сработало. Я добавил одну строку

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// EPField.hpp
 
#ifndef EPFIELD_HPP
#define EPFIELD_HPP
 
class Field; // вот эта строка
 
#include "ErrorProcessing.hpp"
#include "Field.hpp"
 
class EPField : public ErrorProcessing {
    public:
        EPField(ErrorText ex_error_text, Field* ex_error_field);
 
    private:
        void print_variables() const;
 
        Field *error_field;
};
P.S. Все что вы расписали, я знал ранее. В книге Страуструпа я читал про объявление класса и позднее его определение. Однако, я не понимал, зачем это нужно. А теперь все понял
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
10.11.2018, 13:30
Цитата Сообщение от ELchemist Посмотреть сообщение
Кстати, советую использовать :
#pragma once
Разве эта прагма уже вошла в стандарт? Насколько мне известно, нет. Защитные макросы #ifndef / #define / #endif являются более универсальным решением.
0
 Аватар для ELchemist
2 / 2 / 0
Регистрация: 14.03.2018
Сообщений: 51
10.11.2018, 13:58  [ТС]
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Разве эта прагма уже вошла в стандарт? Насколько мне известно, нет. Защитные макросы #ifndef / #define / #endif являются более универсальным решением.
Если компилятор поддерживает что-то более лучшее, чем в стандарте, то почему бы не использовать?
0
4 / 2 / 2
Регистрация: 11.02.2018
Сообщений: 24
10.11.2018, 16:45
ELchemist, рад был помочь, удачи вам. Но честно говоря, Страуступов не лучший для чтения, сам начинал его читать, но мне он как-то вообще не понравился. Стивен Пратта для меня первооткрыватель c++. И пока считаю его очень хорошим для новичков.
COKPOWEHEU, а насчёт стандарта, это не то, чему обязательно надо следовать программисту. До c++11 неужели вы ни разу не пользовались многопоточностью или лямбда-функцией? Стандарт отстаёт от развития возможностей и необходимостью инструментов в языке. Thread, filesystem, SmarPointer, asio(его даже пока нет, насколько я знаю в стандарте) и многое другое, неужели вы можете от этого отказаться без стандарта. С C++99 до C++11 года стандарт не обновлялся, за это время произошли многие изменения в компьютерном мире, которые перевернули требования к языкам программированиям. Не особо поменялось требования только к программированию на микроконтроллерах(так как там надо использовать только низкоуровневые средства C в основном). Так что следовать стандарту во всем глупо(имеется ввиду использовать средства только относящие к стандарту). Я понимаю, что это может вызвать непереносимый код. Но #pragma once во многих компиляторах распространена. Надо понимат, когда, где и в каких случаях это можно использовать, а когда надо жертвовать чем-то, для переносимости/производительности и т.д.
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
11.11.2018, 03:16
Цитата Сообщение от ELchemist Посмотреть сообщение
Если компилятор поддерживает что-то более лучшее, чем в стандарте, то почему бы не использовать?
То есть того, что это ухудшает переносимость и не дает каких либо плюсов уже недостаточно?
Цитата Сообщение от emik_g777 Посмотреть сообщение
До c++11 неужели вы ни разу не пользовались многопоточностью или лямбда-функцией?
Да я ими и сейчас на особо пользуюсь, мне Си привычнее. Да и многопоточность из соображений переносимости переписывал на системных библиотеках pthread / winapi. Именно потому что стандартизованные потоки не завезли.
Цитата Сообщение от emik_g777 Посмотреть сообщение
Стандарт отстаёт от развития возможностей и необходимостью инструментов в языке.
Ну не надо путать необходимость со следованием моде.
Цитата Сообщение от emik_g777 Посмотреть сообщение
и многое другое, неужели вы можете от этого отказаться без стандарта
Разумеется. Пока что от всех этих полустандартных расширений больше вреда: пихают куда надо и куда не надо, а потом разбирайся как это заставить работать.
Цитата Сообщение от emik_g777 Посмотреть сообщение
Надо понимат, когда, где и в каких случаях это можно использовать, а когда надо жертвовать чем-то, для переносимости/производительности и т.д.
И чем же приходится жертвовать в случае #ifdef / #define / #endif по сравнению с #pragma once?
.
Впрочем, на счет некоторых современных расширений стандарта готов признать свою излишнюю консервативность: отчасти просто лень за всем этим следить. Однако возражение на счет переносимости все еще считаю объективным. Как и на счет конкретно сравнения защит от множественного включения.
0
 Аватар для ELchemist
2 / 2 / 0
Регистрация: 14.03.2018
Сообщений: 51
13.11.2018, 14:22  [ТС]
Цитата Сообщение от emik_g777 Посмотреть сообщение
Но честно говоря, Страуступов не лучший для чтения, сам начинал его читать, но мне он как-то вообще не понравился. Стивен Пратта для меня первооткрыватель c++. И пока считаю его очень хорошим для новичков.
Если честно, я уже не новичок в программировании. У меня на счету несколько книг по C++, включая книгу Страуструпа "Язык программирования C++". Еще где-то 3 месяца назад я прочел "Совершенный код" Стива Макконнелла. Именно Макконнелл сумел объяснить мне, зачем нужно ООП, а Страуструп объяснил мне полиморфизм
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.11.2018, 14:22
Помогаю со студенческими работами здесь

Как правильно передать в функцию указатель на двумерный массив?
Сабж #include &lt;windows.h&gt; #include &lt;stdio.h&gt; using namespace std; //ОТ безысходности сделал матрицу глобальной int A = {2,...

Не могу понять, как правильно передать указатель на объект в файл
Есть вектор v, который надо отсортировать. Есть класс MergeSort, который это должен делать, он содержит в качестве параметра указатель на...

Как правильно передать подсчитанное значение массива в класс?
в методе ReadData я считываю файл и заношу данные в двумерный массив massiv, инициализирую тоже в этом методе потому что заранее не...

Передать в DLL указатель на класс
В основной программе хочю сделать чтото типа class fprognoz { public: double End_chen; int rezult; __int64 ...

Передать указатель функции через класс?
Привет. typedef void ( *Callback )( float* pFloat ); void Func(Callback function) { // other code.. }


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru