質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1742閲覧

関数ポインタの使い方に関して

Iwan

総合スコア35

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/12/23 07:24

【使用環境】
Windows10
VisualStudio2019 16.11.2

【状況】
関数ポインタについてサンプルプログラムを作っていて
下記コードで
・「C2664 'void appManager::EntryFunc(void (__cdecl ParamClass:: )(void))': 引数 1 を 'void (__cdecl appUpdate:: )(void)' から 'void (__cdecl ParamClass::* )(void)' へ変換できません。**」
と言うエラーが出るのですが解決法がわからないのと、そもそも関数ポインタの使い方が
これで合っているのかもわからない為、質問させて頂きました。

【コード】

■ appManager.h(一部省略) struct ParamClass { // 関数ポインタ typedef void (ParamClass::* LPFN_FUNC)(void); LPFN_FUNC m_pFunc; }; class appManager { public: appManager(); ~appManager(); private: std::vector< ParamClass> m_ParamList; private: // m_pFuncに登録された関数をコールする関数 void ExecFunc(void); public: // 関数の登録処理 void EntryFunc(void (ParamClass::*lpFunc)()); }; ■ appManager.cpp(一部省略) appManager::appManager() { } appManager::~appManager() { } // 登録した関数の実行 void appManager::ExecFunc() { auto func_list = m_ParamList.size(); for (int i = 0; i < func_list; i ++) { m_ParamList.at(i).m_pFunc; } } // 関数の登録 void appManager::EntryFunc(void (ParamClass::* LPFN_FUNC)()) { std::unique_ptr<ParamClass> class_ptr = std::make_unique<ParamClass>(); class_ptr->m_pFunc = LPFN_FUNC; m_ParamList.push_back(*class_ptr); class_ptr.release(); } ■ appUpdate.h(一部省略) class appUpdate { public: appUpdate(); ~appUpdate(); private: // appManagerのParamClassに登録する関数 void UpdateRender(); }; ■ appUpdate.cpp(一部省略) appUpdate::appUpdate() { appManager* pManager = new appManager(); pManager->EntryFunc(&appUpdate::UpdateRender); delete pManager; } appUpdate::~appUpdate() { } void appUpdate::UpdateRender() { }

宜しくお願いします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんなん↓じゃダメっすか?

C++

1#include <iostream> 2#include <functional> 3#include <vector> 4 5class appManager { 6public: 7 appManager() {} 8 ~appManager() {} 9 10private: 11 12 std::vector<std::function<void(void)>> m_ParamList; 13 14public: 15 void ExecFunc() { 16 for ( auto fn : m_ParamList ) fn(); 17 } 18 19 // 関数の登録処理 20 void EntryFunc(std::function<void(void)>&& func) { 21 m_ParamList.emplace_back(func); 22 } 23}; 24 25void f1() { 26 std::cout << "f1()\n"; 27} 28 29class foo { 30public: 31 void f3() { std::cout << "f3()\n"; } 32}; 33 34int main() { 35 appManager mng; 36 37 mng.EntryFunc(&f1); // 関数ポインタ 38 mng.EntryFunc([](){ std::cout << "f2()\n"; }); // lambda式もOK 39 foo f; 40 mng.EntryFunc([&f]() { f.f3(); }); // メンバ関数はlambdaでくるんで 41 42 mng.ExecFunc(); // 全部呼んじゃうぞ! 43}

[追記] ぢゃ...コレじゃダメっすか?

C++

1#include <iostream> 2#include <vector> 3 4class appUpdate; 5 6struct ParamClass { 7 // 関数ポインタ 8 typedef void (appUpdate::* LPFN_FUNC)(void); 9 LPFN_FUNC m_pFunc; 10 // レシーバ 11 appUpdate* m_pReceiver; 12 ParamClass(appUpdate* recv, LPFN_FUNC func) : m_pReceiver(recv), m_pFunc(func) {} 13 void execute(); 14}; 15 16class appManager { 17public: 18 appManager() {} 19 ~appManager() {} 20 21private: 22 std::vector<ParamClass> m_ParamList; 23 24public: 25 // m_pFuncに登録された関数をコールする関数 26 void ExecFunc(void) { 27 for ( auto& param : m_ParamList ) param.execute(); 28 } 29 30 // 関数の登録処理 31 void EntryFunc(ParamClass param) { 32 m_ParamList.emplace_back(param); 33 } 34}; 35 36class appUpdate { 37public: 38 appUpdate() {} 39 ~appUpdate() {} 40 41public: 42 // appManagerのParamClassに登録する関数 43 void UpdateRender() { std::cout << "appUpdate::UpdateRender()\n"; } 44}; 45 46void ParamClass::execute() { (m_pReceiver->*m_pFunc)(); } 47 48int main() { 49 appManager mngr; 50 51 appUpdate app1; 52 appUpdate app2; 53 54 mngr.EntryFunc(ParamClass(&app1, &appUpdate::UpdateRender)); 55 mngr.EntryFunc(ParamClass(&app2, &appUpdate::UpdateRender)); 56 57 mngr.ExecFunc(); 58}

投稿2021/12/23 07:46

編集2021/12/24 11:20
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Iwan

2021/12/24 00:40 編集

回答ありがとうございます。 自分としては今回は struct ParamClass { // 関数ポインタ定義 }; class appManager {    ParamClass } の形は変えずに実装可能なら実装したいと考えているのですが 難しいでしょうか。 この形を崩したくない理由としては今後メンバとして設定を 追加していきたいと考えている為、「設定専用構造体」を用意したいと 考えている為です。
fana

2021/12/24 01:21

> 難しいでしょうか 「難しい」とは何を指してのことか? ParamClass のメンバ m_pFunc の型を変えれば良いだけの話では.(そもそもそこが問題になってるわけだし)
episteme

2021/12/24 06:48

↑たとえそうしたところで void appManager::ExecFunc() で頓挫するんじゃないかな... (やって見りゃわかるけど) メンバ関数はレシーバーとなるオブジェクトなしには呼び出せないから。
episteme

2021/12/24 11:21

...追記しました。
Iwan

2021/12/26 05:54 編集

epistemeさん。 返信が遅くなり申し訳ありません。 追記して頂いたコードでエラーも出ず実行できました。 この方法だと今後追加していく時は -------------------------------------------------------------- typedef void (appUpdate::* LPFN_FUNC)(void); LPFN_FUNC m_pFunc; // レシーバ appUpdate* m_pReceiver; ParamClass(appUpdate* recv, LPFN_FUNC func) : m_pReceiver(recv), m_pFunc(func) {} -------------------------------------------------------------- と同じ記述をParamClass内に増やしていくと言う事でしょうか? 例)、appTitleの関数登録処理を増やしたい場合 -------------------------------------------------------------- // 関数ポインタ typedef void (appTitle::* LPFN_FUNC)(void); LPFN_FUNC m_pFuncT; // レシーバ appTitle* m_pReceiver; ParamClass(appTitle* recv, LPFN_FUNC func) : m_pReceiver(recv), m_pFunc(func) {} -------------------------------------------------------------- 的な形で
episteme

2021/12/26 07:37 編集

僕の許可が要るわけじゃなし、やってみたらいいぢゃん。 > この方法だと今後追加していく時は 何に何を追加するんです?
fana

2021/12/27 03:01

> ParamClass のメンバ m_pFunc の型を変えれば良いだけの話では というのは…… 回答内容が std::function ↓ それに対して,ParamClass とかいうのを使う形は崩したくないという話 ↓ じゃあ ParamClass のメンバ m_pFunc の型を std::function<void(void)> に変えれば良いのでは ……っていう.
episteme

2021/12/27 03:10 編集

↑ いっそ typedef std::function<void(void)> ParamClass; でも良いんじゃないか...っていう
fana

2021/12/27 03:55 編集

でもそしたら > 今後メンバとして設定を追加していきたいと考えている為、「設定専用構造体」を用意したい っていう話が来て無限ループするんじゃないか…っていう (管理側から見て未知な処理を登録する場所に 誰が 何の 設定をそこに入れる想定なのかわからないけども)
Iwan

2021/12/27 06:55

epistemeさん >この方法だと今後追加していく時は >何に何を追加するんです? こちらですが各シーン毎の処理関数(描画など)登録して一箇所で一括管理する事を想定していました。 そして今後プライオリティの変数等を追加して描画順を変更する実装を追加したいと考えています
episteme

2021/12/27 07:03

...で、問題は解決しましたか?
Iwan

2021/12/27 09:32 編集

記載していただいたコードで実行でき 別シーンの処理関数を追加する際はappUpdateと同じ記述を追加していくことで 対応していきたいと思います。
episteme

2021/12/27 10:54

んじゃcloseしといてね
guest

0

引数の型が ParamClass型のメンバ関数ポインタ である箇所に
appUpdate型のメンバ関数ポインタを渡そうとしているのでダメだという話です.


[補足]

typedef void (ParamClass::* LPFN_FUNC)(void);

この LPFN_FUNC は
「引数無し戻り値無しの ParamClass のメソッド を指す用のポインタの型」
のtypedefです.

投稿2021/12/23 07:37

編集2021/12/23 07:43
fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問