Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.74/19: Рейтинг темы: голосов - 19, средняя оценка - 4.74
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Сохранение указателя на функцию класса

04.12.2019, 10:37. Показов 4154. Ответов 51
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех. Пытаюсь сохранить указатель на функцию класса, получаю ошибку. Расскажите, как сделать то, что мне надо?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int (*globalGet)();
 
class A
{
  public:
  A() {
    m_Var = 7;
    globalGet = get; /* cannot convert ‘A::get’ from type ‘int (A::)()’ to type ‘int (*)()’ */
  }
  
  int get() {
    return m_Var;  
  }
 
  private:
  int m_Var;
};
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.12.2019, 10:37
Ответы с готовыми решениями:

Передача указателя на функцию-член класса
Необходимо передать фунцию-член класса как аргумент в функцию другого класса. Код: Файл main.cpp #include "head.hpp" ...

Хранение в map указателя на функцию-член шаблонного класса
Здравствуйте! Сделал я себе вызов написать джунгли из ООП деревьев, типо, объекты обмениваются между собой сообщениями используя их...

Создание указателя на экземпляр класса, описанного после объявления указателя
Здравствуйте! Проблема в том, что нужно сделать так: class A{ public: B* b = nullptr; }; class B{ public:

51
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.12.2019, 15:00  [ТС]
Студворк — интернет-сервис помощи студентам
DrOffset, спасибо за код.
Я правильно понимаю, что его использовать надо так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include "file.h>
 
int main()
{
  IFile* file = createIFile();
  
  if (openFile(file, "SomeFile"))
    printf("Файл SomeFile успешно открыт!");
  else
    printf("Ошибка при открытии файла SomeFile!");
 
  return 0;
}
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
06.12.2019, 15:37
Цитата Сообщение от d7d1cd Посмотреть сообщение
Я правильно понимаю, что его использовать надо так
Да, типа того.
Там нужна еще функция освобождения объекта (я думаю вы это и так поняли, но на всякий случай упомяну).
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.12.2019, 15:48  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Там нужна еще функция освобождения объекта (я думаю вы это и так поняли, но на всякий случай упомяну).
Это да, понял.
Но вот мне кажется этот код несколько неудобным... Надо переспать с ним Спасибо еще раз!
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 11:46  [ТС]
DrOffset, попробовал сделать программу по Вашему примеру. Для упрощения убрал проверки и функцию открытия. Приведу код:
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
33
// header.h (can use it from C) ----------------------
#ifdef __cplusplus
extern "C" {
#endif
 
struct IFile;
IFile * createIFile();
 
#ifdef __cplusplus
}
#endif
 
// cpp ------------------------------------
#include "header.h"
 
struct IFile
{
};
 
IFile * createIFile()
{
  return new IFile();
}
 
 
// Use in C program --------------------------
#include <stdio.h>
#include "header.h"
 
int main()
{
  IFile* file = createIFile();
}
Модуль CPP создается. При компиляции модуля с функцией main ошибка компиляции в файле header.h на строке IFile * createIFile();: Syntax error: possible missing '{'?, а так же Definition of function IFile requires parentheses.
0
фрилансер
 Аватар для Алексей1153
6455 / 5656 / 1129
Регистрация: 11.10.2019
Сообщений: 15,066
07.02.2020, 11:53
d7d1cd, убери круглые скобки в 22 строке
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 11:59  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
убери круглые скобки в 22 строке
Причем здесь эти скобки? Я ж написал, что модуль CPP собирается, а эти скобки в этом модуле. Не собирается именно сишный модуль. Если поработать препроцессором, то компилятору дают такой код:
C++
1
2
3
4
5
6
7
struct IFile;
IFile * createIFile();
 
int main()
{
  IFile* file = createIFile();
}
Как он это скомпилирует, если структура IFile не определена?
0
фрилансер
 Аватар для Алексей1153
6455 / 5656 / 1129
Регистрация: 11.10.2019
Сообщений: 15,066
07.02.2020, 12:06
Цитата Сообщение от d7d1cd Посмотреть сообщение
Как он это скомпилирует,
вообще, здесь нет использования этой структуры, а предопределение имеется, так что должно скомпилиться

насчёт скобок - если ругалось на эту строку return new IFile();, то компилятор думает, что тут хотят объявить функцию. Поэтому скобки нужно убрать

хотя, вот именно в этой строке и есть использование

тело этой функции нужно перенести в cpp
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
07.02.2020, 12:34
Цитата Сообщение от d7d1cd Посмотреть сообщение
При компиляции модуля с функцией main ошибка компиляции в файле header.h на строке IFile * createIFile();: Syntax error: possible missing '{'?, а так же Definition of function IFile requires parentheses.
main у вас на с или c++?

Добавлено через 2 минуты
Если на С, то заголовочный файл должен быть такой:
C++
1
2
3
4
5
6
7
8
9
10
11
#ifdef __cplusplus
extern "C" {
#endif
 
typedef struct IFile IFile;
 
IFile * createIFile();
 
#ifdef __cplusplus
}
#endif
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 12:35  [ТС]
Алексей1153, еще раз: модуль со строкой return new IFile(); компилируется!
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
07.02.2020, 12:36
Цитата Сообщение от Алексей1153 Посмотреть сообщение
то компилятор думает, что тут хотят объявить функцию. Поэтому скобки нужно убрать
Он не может в данном случае так думать.
Для того, чтобы так думать, нужен неоднозначный синтаксис. А тут все однозначно.
0
фрилансер
 Аватар для Алексей1153
6455 / 5656 / 1129
Регистрация: 11.10.2019
Сообщений: 15,066
07.02.2020, 12:39
d7d1cd, ну и отлично
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 13:26  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Если на С, то заголовочный файл должен быть такой
DrOffset, завелось, спасибо. Всегда напрягало в С, что для объявления переменной структуры надо постоянно писать ключевое словоstruct. Хотя можно сделать typedef.

По поводу того, что надо еще сделать закрытие файла (по сути вызов оператора delete для указателя на IFile). Я правильно понимаю, что здесь только вручную это делать? Ведь если в С коде указатель на IFile выйдет из области видимости, то это никак нельзя отследить автоматически?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
07.02.2020, 13:44
Цитата Сообщение от d7d1cd Посмотреть сообщение
По поводу того, что надо еще сделать закрытие файла (по сути вызов оператора delete для указателя на IFile). Я правильно понимаю, что здесь только вручную это делать?
Делайте функцию
C++
1
2
3
4
5
6
7
8
9
10
11
12
#ifdef __cplusplus
extern "C" {
#endif
 
typedef struct IFile IFile;
 
IFile * createIFile();
void closeIFile(IFile *);
 
#ifdef __cplusplus
}
#endif
внутри нее вызывайте delete.

Добавлено через 3 минуты
Цитата Сообщение от d7d1cd Посмотреть сообщение
Ведь если в С коде указатель на IFile выйдет из области видимости, то это никак нельзя отследить автоматически?
Да, в стандартном C вызывать вручную.

Добавлено через 5 минут
В GCC есть расширение компилятора, которое позволяет задать "очищающую" функцию.
Выглядит это примерно так:
C
1
2
3
4
5
6
7
#include <stdio.h>
#include "header.h"
 
int main()
{
  IFile* file __attribute__ ((__cleanup__(closeIFile))) = createIFile();
}
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 14:01  [ТС]
У меня не GCC...
DrOffset, а как Вы смотрите на такой вариант. В CPP модуле создаем глобальный вектор. В функции createIFile объект IFile создаем на стеке (в принципе, этот класс создан так, чтобы можно было его экземпляры создавать на стеке: он сам размещает свои данные в куче и в деструкторе освобождает их), помещаем его в вектор и возвращаем на него указатель. Когда при завершении программы вектор начнет разрушаться, он вызовет деструкторы у его элементов.
C++
1
2
3
4
5
6
7
std::vector<IFile> files;
 
IFile* createIFile()
{
  files.push_back(IFile());
  return &files.back();
}
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
07.02.2020, 14:05
d7d1cd, я нормально смотрю. Если вам условия позволяют так делать - делайте
Про ограничения этого способа для общего случая вы наверное и сами знаете. Если они вам не мешают, почему бы и нет?
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 14:07  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Про ограничения этого способа для общего случая вы наверное и сами знаете.
Эмм... Может быть и не знаю Озвучьте, если не затруднит.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
07.02.2020, 14:32
d7d1cd,
1) время жизни всех объектов - очень длинное, это может мешать логике вызывающей стороны;
2) если эта функция используется конкуррентно, то нужна сихронизация. А в однопоточном варианте - синхронизация будет замедлять работу;
3) отсутствие ожидаемого поведения. Ресурс возвращен, но тот, кто его получил, им не владеет.
1
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
12.02.2020, 10:05
d7d1cd, добавлю:
C++
1
2
3
4
5
6
7
8
std::vector<IFile> files;
 
IFile* createIFile()
{
  files.push_back(IFile()); // тут возможна реаллокация(если вы напрямую логикой её не "запретите"),
                            // а значит предыдущие возвращенные функцией ссылки становятся невалидными
  return &files.back();
}
Добавлено через 1 минуту

Не по теме:

Хотя это наверное то, что имелось ввиду в п.3 предыдущего поста :)

2
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
12.02.2020, 15:00  [ТС]
zayats80888, да, Вы правы... Печалька, ибо использование классов из С-кода затевалось в том числе для того, чтобы не париться с закрытием файлов...

А что если (щас попрет настоящий говнокод )...
Что если в С++ модуле наряду с вектором файлов завести счетчик созданных файлов. А в С модуль возвращать номер файла в векторе. Вот такое чудо получается:
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
// В "общем" H-файле --------------------------
#ifdef __cplusplus
extern "C" {
#endif
 
unsigned int CreateIFile();
int OpenFile(unsigned int, const char*);
 
#ifdef __cplusplus
}
#endif
 
// В СPP файле ----------------------------------------
class IFile
{  ...  };
 
unsigned int index = 0;
std::vector<IFile> files;
 
unsigned int CreateFile()
{
  files.push_back(IFile());
  return index++;
}
 
int OpenFile(unsigned int id, const char* file)
{
  if (id >= index)
    return -1;
  return files[id].OpenFile(file);
}
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
12.02.2020, 15:25
d7d1cd, что бы избежать реаллокации - самое простое, заменить вектор на какой нибудь std::list
Цитата Сообщение от d7d1cd Посмотреть сообщение
Что если в С++ модуле наряду с вектором файлов завести счетчик созданных файлов. А в С модуль возвращать номер файла в векторе.
Если вас устраивает, то можно так.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.02.2020, 15:25
Помогаю со студенческими работами здесь

Как сделать функцию от указателя на класс и указателя на метод?
Не получается сделать функцию, параметрами которой являются указатель на класс и на метод. Обращаться к классу нужно именно по указателю,...

Создание указателя типа базового класса на экземпляр производного класса
Добрый день! Иногда видел коды, где создавался указатель типа базового класса на объект класса - наследника, для чего это может применяться?

Определить обработчик исключений на преобразование указателя базового класса на указатель производного класса
Класс В является производным от класса А. Определить обработчик исключительной ситуации на преобразование указателя базового класса А на...

Вызов методов класса из двойного указателя на экземпляр класса
Добрый день! Как можно вызвать метод класса по двойному указателя на его экземпляр? struct Point { void getPoint(){}; ...

Зачем передавать в функцию X указатель на callback функцию, если последняя ВНЕШНЯЯ и вызовется БЕЗО ВСЯКОГО УКАЗАТЕЛЯ?
Собсно. То есть ребята, вот пример отсюда: http://www.cplusplus.com/reference/algorithm/count_if/ // count_if example #include...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru