B級科学者もどきの憂鬱

とある理系になりきれない奴のつれづれなる活動記

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

群を継承して実装したい

最近だいぶ忙しさが無くなってきたので、
TIPSエンジンをC++で書き直しています。
で、どうせなら汎用的なライブラリにしてしまおうと、
色々と定義していたら、いつの間にか複素数クラスを作っていました。

より良い物を求めるのはいいことだとは思いますが、
いくら何でも基礎からやり過ぎのような気がします。
でもまぁ今作っておけば、今後の開発にも役立つでしょう。多分。

どうせなら多倍精度小数や四元数も欲しいと思ったので、
複素数クラスのメンバ関数をうまく利用して作れないかと考えたのですが、
静的型付け言語では中々難しいようですね。

具体的には、メンバを持たず、演算だけを宣言したテンプレートクラスを用意し、
それを多重継承していくことで、クラスの性質だけを定義しようと考えました。
まぁつまり、代数的構造(群など)をインターフェースにして、
それを継承することでクラスの性質を定義しようというものです。

コードとしてはこんな感じです。


/*加算を演算とする群インターフェース*/
template <typename ValueType>
struct IAddGroup
{
virtual ValueType operator+(const ValueType&) const=0;
virtual ValueType& operator+=(const ValueType&)=0;
virtual ValueType operator-(const ValueType&) const=0;
virtual ValueType& operator-=(const ValueType&)=0;
virtual ValueType operator-() const=0; /*逆元を計算*/
virtual ValueType GetZero() const=0; /*単位元を取得*/
virtual ~IAddGroup(){};
};

/*複素数クラス 乗算なども必要だが今回は省略*/
template <typename ValueType>
struct Complex :
public AddGroup< Complex<ValueType> >
{
ValueType r, i; /*実部と虚部*/

virtual ValueType operator+(const ValueType& value) const {
this->r=value.r;
this->i=value.i;
}
virtual ValueType& operator+=(const ValueType& value) {
return *this=*this+value;
}
/*減算などの実装も、上と同じように出来るので省略*/

/*コンストラクタ等も省略*/
};


群インターフェースには実装はありません。
演算のみが純粋仮想関数で宣言されています。
それをComplexクラスで継承することで、
強制的に演算を実装させることが出来ます。

こうして、群の性質を継承したクラスを作れる訳ですが、
本来群というのは、演算方法(仮に+とします)、逆元の取り方、
そして単位元の三つが分かれば、+=、-、-=の演算は、
全て実装出来るはずですよね。

ということは、群インターフェースではなく群クラスにして、
演算のいくつかだけを純粋仮想関数にするだけでも良さそうなものです。
つまり、Complexクラスのoperator+=などの実装は、
IAddGroupに書いてしまいたいのですが、うまく行きません。

まぁそりゃそうです。もしIAddGroupにComplexの+=の実装を書くと、
thisポインタはIAddGroupを示すので、演算するためのメンバが無くなります。
関数オブジェクトを用いるなど、実現自体は一応可能なのですが、
もっと単純に、出来れば継承元にメンバを持たせずに実現したいところです。

このために色々考えてはみたのですが、上手いアイデアが思いつきませんでした。
現段階でも、性質の継承という目的は一応果たせていますし、
継承先では+と+=でそれぞれコードを最適化した方が大抵速いはずなので、
とりあえずこれで開発していくつもりです。

でもやっぱり気になるのは事実。
どなたか良い方法を知りませんか?

FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。