• 締切済み

メンバ関数ポインタを値とするコンテナの定義方法

こんにちは、boundaryといいます。 あるクラスのメンバ関数のポインタをmapで管理したいので すが、定義でエラーになってしまいます。 class CFunc { private: bool FuncA(); bool FuncB(); }; このようなクラスに対して、 template <class T> class FuncMap { private: typedef bool (T::*Func)(); typedef map<int, T::Func> _FuncMap; _FuncMap FMap; public: void set(int, T::Func); T::Func search(int); }; を用意しました。 template <class T> void FuncMap<T>::set(int i, T::Func pFunc) { FMap.insert(pair<int , T::Func>(i ,pFunc)); } template <class T> T::Func FuncMap<T>::search(int i) { map<T::Func, int>::iterator FuncMapIte; FuncMapIte = FMap.find(i); return T::Func; } と書いたのですが、 error C2244: 'FuncMap<T>::set' : 関数のオーバーロードが解決できません。 error C2954: テンプレートの定義はネストできません。 error C2244: 'FuncMap<T>::search' : 関数のオーバーロードが解決できません。 との事です。 色々試行錯誤したのですが、うまくいきません。 定義のどこがいけないのでしょうか? よろしくお願いします。 VC6.0SP5 WINDOWS2000です。

みんなの回答

回答No.2

# '先生'と呼ばれるのはイヤ。 #include <iostream> #include <map> template <class T> class FuncMap { private: typedef bool (T::*Func)(); typedef std::map<int, Func> _FuncMap; _FuncMap FMap; public: void set(int n, Func f) { FMap[n] = f; } Func search(int n) { return FMap[n]; } }; #if 0 // [1] class CFunc { private: FuncMap<CFunc> FMAP; bool FuncA() { std::cout << "CFunc::FuncA\n"; return true; } bool FuncB() { std::cout << "CFunc::FuncB\n"; return true; } public: CFunc(); void Execute(int); }; CFunc::CFunc() { FMAP.set(0, CFunc::FuncA); FMAP.set(1, CFunc::FuncB); } void CFunc::Execute(int i) { (this->*(FMAP.search(i)))(); } #else // [2] class CFunc : public FuncMap<CFunc> { bool FuncA() { std::cout << "CFunc::FuncA\n"; return true; } bool FuncB() { std::cout << "CFunc::FuncB\n"; return true; } public: CFunc(); void Execute(int); }; CFunc::CFunc() { set(0, CFunc::FuncA); set(1, CFunc::FuncB); } void CFunc::Execute(int i) { (this->*search(i))(); } #endif int main() { CFunc cf; cf.Execute(0); cf.Execute(1); return 0; } > templateクラスの定義は.hと一緒に書かなくてはいけないのでしょうか? YES.

noname#4877
質問者

お礼

ありがとうございました。m(_ _)m 御本を読み精進します。

noname#4877
質問者

補足

私が点を付けるのもおこがましいと思いますので”該当な し”にしてます。

回答No.1

#include <map> #include <iostream> class CFunc { public: bool FuncA() { std::cout << "CFunc::FuncA\n"; return false; } bool FuncB() { std::cout << "CFunc::FuncB\n"; return true; } }; template <class T> class FuncMap { private: typedef bool (T::*Func)(); typedef std::map<int, Func> _FuncMap; _FuncMap FMap; public: void set(int, Func); Func search(int); }; template <class T> void FuncMap<T>::set(int i, Func pFunc) { FMap.insert(_FuncMap::value_type(i ,pFunc)); } template <class T> FuncMap<T>::Func FuncMap<T>::search(int i) { _FuncMap::iterator FuncMapIte; FuncMapIte = FMap.find(i); return FuncMapIte->second; } int main() { FuncMap<CFunc> m; m.set(0, CFunc::FuncA); m.set(1, CFunc::FuncB); CFunc f; (f.*(m.search(0)))(); (f.*(m.search(1)))(); return 0; }

noname#4877
質問者

補足

こんにちは、episteme先生。m(_ _)m 私はイマイチ文の評価の理解度が低く、いつもこのような疑問にぶつかってしまいます。 型情報を渡さないといけない所にアドレスを渡してたり、アドレスを渡さないといけない所に 型情報を渡してたり・・・。 T::Func search(int)はハチャメチャでした。スミマセン。(;w;) お手数だとは思いますがさらに教えていただきたい事があります。 CFuncのメンバ関数をpublicにするのが嫌と思い、方法を2つ考えました。 1.FuncMapをCFuncのプライベートメンバにする。 2.FuncMapをCFuncから派生させる。 やってみました。 //1.の方法...宣言部 template <class T> class FuncMap { private: typedef bool (T::*Func)(); typedef std::map<int, Func> _FuncMap; _FuncMap FMap; public: void set(int, Func); Func search(int); }; class CFunc { private: FuncMap<CFunc> FMAP; bool FuncA(); bool FuncB(); public: CFunc(); void Execute(int); }; //1.の方法...定義部 CFunc::CFunc() { FMAP.set(0, CFunc::FuncA); FMAP.set(1, CFunc::FuncB); } void CFunc::Execute(int i) { (CFunc.*(FMAP.search(i)))(); } error C2143: 構文エラー : ')' が '.*' の前に必要です。 error C2059: 構文エラー : ')' とエラーが出ます。 どのように定義すればよいでしょうか? //2.の方法...宣言部 template <class T> class FuncMap { private: typedef bool (T::*Func)(); typedef std::map<int, Func> _FuncMap; _FuncMap FMap; protected: void set(int, Func); Func search(int); }; template<class T> class CFunc : public FuncMap<T>{ private: bool FuncA(); bool FuncB(); public: CFunc(); void Execute(int); }; //2.の方法...定義部 template<class T> bool CFunc<class T>::FuncA() { cout << "in CFunc::FuncA()" << endl; return true; } template<class T> bool CFunc::FuncB() { cout << "in CFunc::FuncB()" << endl; return true; } template<class T> CFunc::CFunc() { set(0, CFunc::FuncA); set(1, CFunc::FuncB); } template<class T> void CFunc::Execute(int i) { (CFunc.*(search(i)))(); } error C2371: 'T' : 再定義されています。異なる基本型です。 error C2039: 'FuncA' : 'CFunc<class T>' のメンバではありません。 error C2955: 'CFunc' : クラスのテンプレート名で仮引数リストの指定がありません。 : 'CFunc' の宣言を確認してください。 error C2955: 'CFunc' : クラスのテンプレート名で仮引数リストの指定がありません。 : 'CFunc' の宣言を確認してください。 error C2955: 'CFunc' : クラスのテンプレート名で仮引数リストの指定がありません。 : 'CFunc' の宣言を確認してください。 これまたたくさんエラーが出ます。 スミマセン、どのように定義すればよいでしょうか? もう一つわからない所があります。 templateクラスの定義は.hと一緒に書かなくてはいけないのでしょうか? 上記の場合、EventFuncTest.hにクラス宣言、EventFuncTest.cppに定義を書いたのですが リンクエラーになりました。 ぶしつけな質問で申し訳ありませんがどうぞよろしくお願いします。 boundary