ページ 11

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

Posted: 2015年1月29日(木) 23:38
by cactas
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ファイルにも構文エラーが発生する

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

Posted: 2015年1月29日(木) 23:50
by みけCAT
とりあえず、こうすると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;}

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

Posted: 2015年1月30日(金) 00:03
by cactas
みけCAT様
素早いご回答、ありがとうございます。
クラスの外でメンバ関数ポインタを作ってやればよいということですね。
ただ、管理のしやすさから、できたらクラス内で作成したいです。

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

Posted: 2015年1月30日(金) 00:18
by みけCAT
コンストラクタで代入する…とかでしょうか?

コード:

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;}

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

Posted: 2015年1月30日(金) 00:46
by cactas
みけCAT様
コンストラクタで代入するという手があるのですね。
とりあえず、この部分はコンパイルできました。
ありがとうございました。

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

Posted: 2015年1月30日(金) 05:25
by milfeulle
蛇足ながら…

(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
}
どちらをお望みでしょう? 考えてみてください。

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

Posted: 2015年1月30日(金) 08:17
by みけCAT
milfeulle さんが書きました:蛇足ながら…

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

コード:

struct S {
	int a[4] = { 1, 2, 3, 4 }; // error
};
C++11ならできます。このコードも警告なしでコンパイルが通りました。

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

Posted: 2015年1月30日(金) 09:10
by nullptr
milfeulle さんが書きました:(1) クラス内で直接初期化はできない(ポインタとか関係ないです)

コード:

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

オフトピック
ところで、最初のコードの16行目に全角綴じ括弧があるのは誰も触れないのだろうか?

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

Posted: 2015年1月30日(金) 19:10
by milfeulle
これは失礼しました; ただ手元のVS Express2013だとerror C2536がでてコンパイルできないんですよね…。

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

Posted: 2015年1月30日(金) 19:56
by nullptr
オフトピック
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
で動作するのを確認しました。