個人的に調べた(個人的なものならOKなはず(意味深))
せっかく調べたんだし、いずれ困ったりするときの役に立てばいいかな程度の雑記です
知っといても損はないようなマニアックな知識をご提供(?)
ちなみに、マニアックな内容だしある程度の知識がないと
わからないかもしれないので
講座みたいな内容では書かないのでご注意
(全部説明するのはめんどいともいう)
実行環境はVisualStudio2005以降なら動くはず
実際に動かすのがたぶん一番です。
プリプロセッサ応用編
プリプロセッサというのは
#define なんとか
#include <ファイル名>
でも使い方次第ではなんかいろいろ化けそうな気がします
特に#と##は・・・
#define X(A) #A
で変数(関数、クラス)名に展開
#define X(A) str##A
はstr(文字列)にAの変数(関数、クラス)名を連結させる
#include ファイル名
でファイルの内容を展開
(実はプリプロセッサの処理なのでプログラム途中で書いてもいい、
さらに開くものがテキスト形式ならば拡張子はなんでもいいっぽい)
#define X
#undef X
を繰り返してるのはXで定義を統一してるためだけ(Xに深い意味はない)
んで今回は列挙体を子クラス配列の添え字にして、親クラスにアップキャストしてみる
とりあえずファイルふたつ用意
//Fruits.txt X(Apple) X(Grape) X(Banana)
//main.cpp #include <iostream> using namespace std; #define X(A) A, enum{ #include "Fruits.txt" }; #undef X #define X(A) #A, const char *Fstr[]={ #include "Fruits.txt" }; #undef X // 関数 void Func_Apple(){cout << "This is Apple" << endl;}; void Func_Grape(){cout << "This is Grape" << endl;}; void Func_Banana(){cout << "This is Banana" << endl;}; #define X(A) Func_##A, void (*func[])() = { #include "Fruits.txt" }; #undef X class Fruits { public: virtual void Out(){} }; class CApple: public Fruits {public: virtual void Out(){cout << "An Apple" << endl;}}; class CGrape: public Fruits {public: virtual void Out(){cout << "An Grape" << endl;}}; class CBanana: public Fruits {public: virtual void Out(){cout << "An Banana" << endl;}}; template <class T> Fruits *createFruits(){ return new T;} #define X(A) createFruits<C##A>, Fruits *(*create[])() = { #include "Fruits.txt" }; #undef X int main() { #define strgen1(x) "x" #define strgen2(x) x #define strgen3(x) #x char *p, *str = "abc"; p = strgen1(str); /* p = "x" */ cout << p << endl; p = strgen2(str); /* p = "abc" */ cout << p << endl; p = strgen3(str); /* p = "str" */ cout << p << endl; #define symadd(x, y) sym##x + sym##y int sym1 = 3, sym2 = 5; int i = symadd(1, 2); /* sym1 + sym2 */ cout << i << endl; cout << Apple << endl; cout << Grape << endl; cout << Banana << endl; cout << Fstr[Apple] << endl; cout << Fstr[Grape] << endl; cout << Fstr[Banana] << endl; func[Apple](); func[Grape](); func[Banana](); Fruits *fruits1 = create[Apple](); Fruits *fruits2 = create[Grape](); Fruits *fruits3 = create[Banana](); fruits1->Out(); fruits2->Out(); fruits3->Out(); delete fruits1; delete fruits2; delete fruits3; return 0; }
列挙体を添え字でわたせば、
そのクラスをアップキャストして使えるようにできる
使い道的にはぅ〜ん・・・あるようなないような・・・
あたりまえだけど関数の仕様とかクラスの仕様とかは
どのみち書かないといけないしなぁ・・・