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

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

04.12.2019, 10:37. Показов 4098. Ответов 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
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
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
6446 / 5642 / 1128
Регистрация: 11.10.2019
Сообщений: 15,008
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
6446 / 5642 / 1128
Регистрация: 11.10.2019
Сообщений: 15,008
07.02.2020, 12:06
Цитата Сообщение от d7d1cd Посмотреть сообщение
Как он это скомпилирует,
вообще, здесь нет использования этой структуры, а предопределение имеется, так что должно скомпилиться

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

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

тело этой функции нужно перенести в cpp
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
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
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.02.2020, 12:36
Цитата Сообщение от Алексей1153 Посмотреть сообщение
то компилятор думает, что тут хотят объявить функцию. Поэтому скобки нужно убрать
Он не может в данном случае так думать.
Для того, чтобы так думать, нужен неоднозначный синтаксис. А тут все однозначно.
0
фрилансер
 Аватар для Алексей1153
6446 / 5642 / 1128
Регистрация: 11.10.2019
Сообщений: 15,008
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
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
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
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.02.2020, 14:05
d7d1cd, я нормально смотрю. Если вам условия позволяют так делать - делайте
Про ограничения этого способа для общего случая вы наверное и сами знаете. Если они вам не мешают, почему бы и нет?
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
07.02.2020, 14:07  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Про ограничения этого способа для общего случая вы наверное и сами знаете.
Эмм... Может быть и не знаю Озвучьте, если не затруднит.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
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
Ответ Создать тему
Новые блоги и статьи
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru