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

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

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

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

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

3回答

1107閲覧

[Dxlib]関数ポインタを引数にもつ関数を作成したい

THETA97556919

総合スコア5

C++

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

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

1クリップ

投稿2021/05/18 12:39

編集2021/05/18 12:48

前提・実現したいこと

関数ポインタを引数に持つ関数を作成したい。

実装したいものは、以下のように関数の入った箱(MethodBox)とそれを読むリーダーがあり、リーダーは読み込んだ関数をキューへ保存していき、一番右端のMethodBoxを読み終わったら、順次キューに入った関数を実行していくようなシステムを作りたい。
イメージ説明

発生している問題・エラーメッセージ

C2664'MethodBox::MethodBox(int,int,int,int,const char *,Method::DRAW)': 引数 6 を '_Ty' から 'Method::DRAW' へ変換できません。 DxLibTemplate2017 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\include\xutility

該当のソースコード

関数ポインタの定義 Method.h

C++

1#pragma once 2#include <DxLib.h> 3 4class Method 5{ 6public: 7 Method() = default; 8 ~Method() = default; 9 10 typedef void (*DRAW) (); //円を描画する関数のポインタ 11 12 void RedCircle() 13 { 14 DrawCircle(100, 100, 10, GetColor(255, 0, 0)); 15 } 16 17 void BlueCircle() 18 { 19 DrawCircle(100, 100, 10, GetColor(0, 0, 255)); 20 } 21};

関数を持つ箱 MethodBox.h

C++

1#pragma once 2 3#include "Task.h" 4#include "Method.h" 5 6class MethodBox : public Task //このように継承するとMethodBoxを使用する関数からもTaskの公開メンバをいじれる 7{ 8private: 9 int m_x, m_y, m_sizeX, m_sizeY; //箱の位置・大きさ 10 const char* m_str; //箱に書かれている文字 11 Method::DRAW m_fp; //読まれると実行される関数のポインタ 12 13public: 14 MethodBox(int _x, int _y, int _sizeX, int _sizeY, const char* _str, Method::DRAW _fp); 15 ~MethodBox() = default; 16 17 bool update() override; 18 void draw() const; 19 void move(); //D&D 20};

Method.cpp

C++

1#include "MethodBox.h" 2#include "Define.h" 3#include "DxLib.h" 4 5MethodBox::MethodBox(int _x, int _y, int _sizeX, int _sizeY, const char* _str, Method::DRAW _fp) 6{ 7 m_x = _x; 8 m_y = _y; 9 m_sizeX = _sizeX; 10 m_sizeY = _sizeY; 11 12 m_str = _str; 13 m_fp = _fp; 14} 15 16bool MethodBox::update() 17{ 18 move(); 19 return true; 20} 21 22void MethodBox::draw() const 23{ 24 int width = m_x + GetFontSize(); //文字のx位置 25 int height = m_y + (m_sizeY / 2) - GetFontSize()/2; //文字のy位置 26 27 DrawBox(m_x, m_y, m_x + m_sizeX, m_y + m_sizeY, GetColor(255, 255, 255), true); //四角形の描画 28 DrawFormatString(width, height, GetColor(0,0,0), m_str); //文字の描画 29} 30 31//D&D処理 32void MethodBox::move() 33{ 34 //左クリックされていたら 35 if (GetMouseInput() & MOUSE_INPUT_LEFT) 36 { 37 int mousePosX, mousePosY; 38 39 GetMousePoint(&mousePosX, &mousePosY); //マウスの座標を取得する 40 41 //クリックした座標がMethodBoxの範囲内であれば、 42 if 43 ( 44 (mousePosX >= m_x) && (mousePosX <= (m_x + m_sizeX)) //X範囲 45 && 46 (mousePosY >= m_y) && (mousePosY <= (m_y + m_sizeY)) //Y範囲 47 ) 48 while (GetMouseInput() & MOUSE_INPUT_LEFT) //左クリックされている間、 49 { 50 GetMousePoint(&mousePosX, &mousePosY); 51 52 //マウスカーソルが画面内であれば 53 if(mousePosX > 0 && mousePosX < Define::WIN_W && mousePosY > 0 && mousePosY < Define::WIN_H) 54 { 55 //MethodBoxの座標を変更 56 m_x = mousePosX - (m_sizeX / 2); 57 m_y = mousePosY - (m_sizeY / 2); 58 } 59 60 } 61 } 62}

MethodBox生成 GameScene.cpp

C++

1#include "GameScene.h" 2#include <DxLib.h> 3 4using namespace std; 5 6//このシーンで使用するオブジェクトの生成 7GameScene::GameScene() 8{ 9 m_field = make_shared<Field>(); 10 m_reader = make_shared<Reader>(); 11 m_methodBox = make_shared<MethodBox>(200,200,130,50,"赤い丸を表示", &Method::RedCircle); 12} 13 14//現在のシーンのフレーム処理 15bool GameScene::update() 16{ 17 m_field->update(); 18 m_reader->update(); 19 m_methodBox->update(); 20 return true; 21} 22 23//現在のシーンの描画処理 24void GameScene::draw() const 25{ 26 m_field->draw(); 27 m_reader->draw(); 28 m_methodBox->draw(); 29} 30

試したこと

Typedefの使い方などを調べなおした。
関数のポインタを使用する -C++プログラミング

補足情報(FW/ツールのバージョンなど)

windows10 VisualStudio2019
プログラミング初心者です。足りない情報などあれば追記いたしますのでご連絡ください。

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

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

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

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

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

episteme

2021/05/18 12:44

MethodBox のコンストラクタ(MethodBox::MethodBox)を呼んでるのはどこですか?
THETA97556919

2021/05/18 12:46

すぐに追記いたします!すみません!
int32_t

2021/05/18 13:09

提示されているコードでは Method::RedCircle() は this に依存していないので static を付けられますが、MethodBox に渡したい関数はすべて static メンバ関数か非メンバ関数にできますか?
THETA97556919

2021/05/18 13:19 編集

すみません、本当に初心者すぎて「Method::RedCircle() は this に依存していないので static を付けられます」のところが理解できてません。軽く教えていただけることはできますか? 少し調べてみましたが、グローバル関数のようなものとして捉えても大丈夫ですか?
int32_t

2021/05/18 13:19

すべてを詳細に説明するのは面倒なので質問を変えると、「Methodクラスにデータメンバを足して、Method::RedCircle()からそのデータメンバを参照する予定はありますか?」です。 現状のコードだと「static void RedCircle()」にすれば解決するでしょうけど、もし上記質問の答えが「はい」なら別の解決方法が必要です。
THETA97556919

2021/05/18 13:24 編集

Methodクラスのメンバ変数に参照する関数は今のところ作る予定はないです! おっしゃる通りstaticをつけるとうまく動きました!!詳しい解決法の提示ありがとうございましたm(_ _)m なぜstatic必要なのか、どのような不具合だったのかはまた自分で調べて理解してみます。
guest

回答3

0

現状だと Method::RedCircleMethod::DRAW は型が異なるので代入できません。Method::RedCircle を呼ぶだめには Method 型のインスタンスが必要なのです。

コメントによるとMethod::RedCircleからデータメンバを使う予定はないとのことなので、このメンバ関数をstaticにしてしまえば良いです。

Method.h:

cpp

1 static void RedCircle() 2 {

そもそも関数ポインタを避けるのが今どきのC++の流儀です。typedef void (*DRAW) ();の代わりに

cpp

1 using DRAW = std::function<void(void)>;

これで関数ポインタもメンバ関数もラムダ式も対応できるようになります。
(メンバ関数を代入するにはstd::bindかラムダ式の助けが必要)

例:

cpp

1 m_methodBox = make_shared<MethodBox>(200,200,130,50,"赤い丸を表示", []() { 2 DrawCircle(100, 100, 10, GetColor(255, 0, 0)); 3 });

投稿2021/05/18 13:31

編集2021/05/18 13:37
int32_t

総合スコア21695

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

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

0

自己解決

Method::RedCircle()をメンバ関数から静的メンバ関数にすることで解決した。

Method.h (一部抜粋)

C++

1static void RedCircle() 2 { 3 DrawCircle(100, 100, 10, GetColor(255, 0, 0)); 4 } 5 6static void BlueCircle() 7 { 8 DrawCircle(100, 100, 10, GetColor(0, 0, 255)); 9 }

投稿2021/05/18 13:28

THETA97556919

総合スコア5

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

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

0

m_methodBox = make_shared<MethodBox>(200,200,130,50,"赤い丸を表示", &Method::RedCircle);

あ、こりゃダメです。

Method::DRAW は void (*)() であるのに対し
&Method::RedCircle は void (Method::*)() です。 両者に互換性はありません。

投稿2021/05/18 12:56

episteme

総合スコア16612

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問