[C++]メンバ関数ポインタの取り扱い方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
cactas
記事: 3
登録日時: 5年前

[C++]メンバ関数ポインタの取り扱い方

#1

投稿記事 by cactas » 5年前

C++でプログラミングを始めたばかりの初心者です。
使用環境はwindows8.1、visual studio 2013 expresです。

現在、「龍神録プログラミングの館」様を参考にSTG作成の勉強中なのですが、12章で躓いています。
12章では一部関数ポインタを使用しており、クラス内でそれを実装するにはメンバ関数ポインタにしないといけないとのことで・・・
ロベール様のサイトを参考に作成してみたところ、クラス内で以下のコードができました。

コード:

class ENEMY{
private:
    static enm enemy[ENEMY_MAX]//敵用構造体の作成
    static double rang(double ang){}//省略
    static void enemy_pattern0(int i){}//省略
    static void enemy_pattern1(int i){}//省略
    static void enemy_pattern2(int i){}//省略

//           中略

    static void enemy_pattern10(int i){}//省略
    void (ENEMY::*enemy_pattern[ENEMY_PATTERN_MAX])(int) = {
ENEMY::enemy_pattern0,ENEMY::enemy_pattern1,ENEMY::enemy_pattern2,ENEMY::enemy_pattern3,
ENEMY::enemy_pattern4,ENEMY::enemy_pattern5,ENEMY::enemy_pattern6,ENEMY::enemy_pattern7,
ENEMY::enemy_pattern8,ENEMY::enemy_pattern9,ENEMY::enemy_pattern10};
}
 
しかし、この状態では各要素に
エラー::型"void(*)(int)"の値を使用して型"void(ENEMY::*[11])(int)"のエンティティを初期化することはできません
と表示されます。
いくつか考えられるパターンを試してみましたが、結局コンパイルが通るものはできませんでした。

どのように変えれば、うまく使用できるようになるでしょうか。
回答よろしくお願いします。
以下、試してみたパターンです。

要素の名前空間を省略する、その状態で「&」を頭につける、名前空間を省略せずに「&」をつける
→同様のエラー

関数ポインタの名前空間を省略する、その状態で上記の状態を追加する
→コンパイル時に
error C2536 クラス、構造体、共用体のメンバーは、初期化できません
が表示される。
また、全く触れていないmsxml.hファイルにも構文エラーが発生する

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: [C++]メンバ関数ポインタの取り扱い方

#2

投稿記事 by みけCAT » 5年前

とりあえず、こうするとWandboxでコンパイルが通りました。

コード:

const int ENEMY_MAX = 3;
const int ENEMY_PATTERN_MAX = 3;
typedef int enm;
class ENEMY{
    private:
        static enm enemy[ENEMY_MAX];//敵用構造体の作成
        static double rang(double ang){return ang;}//省略
        static void enemy_pattern0(int i){(void)i;}//省略
        static void enemy_pattern1(int i){(void)i;}//省略
        static void enemy_pattern2(int i){(void)i;}//省略
        static void (*enemy_pattern[ENEMY_PATTERN_MAX])(int); // 利用可能な関数
        void (*my_enemy_puttern)(int); // この敵が利用する関数?
};
void (*ENEMY::enemy_pattern[ENEMY_PATTERN_MAX])(int) = {
    enemy_pattern0,enemy_pattern1,enemy_pattern2
};

int main(void){return 0;}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

cactas
記事: 3
登録日時: 5年前

Re: [C++]メンバ関数ポインタの取り扱い方

#3

投稿記事 by cactas » 5年前

みけCAT様
素早いご回答、ありがとうございます。
クラスの外でメンバ関数ポインタを作ってやればよいということですね。
ただ、管理のしやすさから、できたらクラス内で作成したいです。

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: [C++]メンバ関数ポインタの取り扱い方

#4

投稿記事 by みけCAT » 5年前

コンストラクタで代入する…とかでしょうか?

コード:

const int ENEMY_MAX = 3;
const int ENEMY_PATTERN_MAX = 3;
typedef int enm;
class ENEMY{
    private:
        static enm enemy[ENEMY_MAX];//敵用構造体の作成
        static double rang(double ang){return ang;}//省略
        static void enemy_pattern0(int i){(void)i;}//省略
        static void enemy_pattern1(int i){(void)i;}//省略
        static void enemy_pattern2(int i){(void)i;}//省略
        void (*enemy_pattern[ENEMY_PATTERN_MAX])(int);
        ENEMY() {
            enemy_pattern[0] = enemy_pattern0;
            enemy_pattern[1] = enemy_pattern1;
            enemy_pattern[2] = enemy_pattern2;
        }
};
 
int main(void){return 0;}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

cactas
記事: 3
登録日時: 5年前

Re: [C++]メンバ関数ポインタの取り扱い方

#5

投稿記事 by cactas » 5年前

みけCAT様
コンストラクタで代入するという手があるのですね。
とりあえず、この部分はコンパイルできました。
ありがとうございました。

アバター
milfeulle
記事: 47
登録日時: 6年前
住所: マリーランド
連絡を取る:

Re: [C++]メンバ関数ポインタの取り扱い方

#6

投稿記事 by milfeulle » 5年前

蛇足ながら…

(1) クラス内で直接初期化はできない(ポインタとか関係ないです)

コード:

struct S {
	int a[4] = { 1, 2, 3, 4 }; // error
};
(2) メンバ変数〔関数〕ポインタと、普通のポインタは全く別のものです!

コード:

struct S {
	static void sfunc(int a) { };
	void mfunc(int a) { }
	void (S::*mp[1])(int);
	void (*S::fp[1])(int); // void (*fp[1])(int); と同じです
};

int main() {
	S s;
	s.mp[0] = S::mfunc; // ok
	s.fp[0] = S::mfunc; // error
	s.mp[0] = S::sfunc; // error
	s.fp[0] = S::sfunc; // ok
}
どちらをお望みでしょう? 考えてみてください。
ζ*'ヮ')ζプログラミングはみんなで奏でるシンフォニー

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: [C++]メンバ関数ポインタの取り扱い方

#7

投稿記事 by みけCAT » 5年前

milfeulle さんが書きました:蛇足ながら…

(1) クラス内で直接初期化はできない(ポインタとか関係ないです)

コード:

struct S {
	int a[4] = { 1, 2, 3, 4 }; // error
};
C++11ならできます。このコードも警告なしでコンパイルが通りました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
nullptr
記事: 239
登録日時: 8年前

Re: [C++]メンバ関数ポインタの取り扱い方

#8

投稿記事 by nullptr » 5年前

milfeulle さんが書きました:(1) クラス内で直接初期化はできない(ポインタとか関係ないです)

コード:

struct S {
	int a[4] = { 1, 2, 3, 4 }; // error
};
今どきのナウでヤングなコンパイラだと、C++03オプションでコンパイルしても警告が出る程度でコンパイルできちゃうっていうね。
visual studio 2013なら対応しているはずです。

オフトピック
ところで、最初のコードの16行目に全角綴じ括弧があるのは誰も触れないのだろうか?
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

アバター
milfeulle
記事: 47
登録日時: 6年前
住所: マリーランド
連絡を取る:

Re: [C++]メンバ関数ポインタの取り扱い方

#9

投稿記事 by milfeulle » 5年前

これは失礼しました; ただ手元のVS Express2013だとerror C2536がでてコンパイルできないんですよね…。
ζ*'ヮ')ζプログラミングはみんなで奏でるシンフォニー

アバター
nullptr
記事: 239
登録日時: 8年前

Re: [C++]メンバ関数ポインタの取り扱い方

#10

投稿記事 by nullptr » 5年前

オフトピック
milfeulle さんが書きました:これは失礼しました; ただ手元のVS Express2013だとerror C2536がでてコンパイルできないんですよね…。
おや…?VisualStudio 14と間違えたかな、と思って確認しましたが、やはりちゃんとコンパイルできますね。
https://msdn.microsoft.com/ja-jp/library/hh567368.aspx
対応表にも○がついてます。
ちゃんとアップデートを適用していないか、或いはExpressでは対応していないのですかね(そんなことはないと思うんですが…)。
Microsoft Visual Studio Professional 2013 Version 12.0.31101.00 Update 4
で動作するのを確認しました。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

閉鎖

“C言語何でも質問掲示板” へ戻る