August 30, 2005

継承とコピーコンストラクタ

C++の話です。C++には通常のコンストラクタのほかに、コピーコンストラクタというコピーをつくるためのコンストラクタがあります。
コピーコンストラクタは以下のように使います。

class SomeClass{
    public:
        SomeClass(const SomeClass &some){/* コピー処理ほげ */;}
};

SomeClass some1();
SomeClass some2(some1); //some2はsome1のなんらかのコピー

継承が絡んでくるとどうでしょうか。

class BaseClass{
    public:
        BaseClass(const BaseClass &base){}
};
class SubClass : public BaseClass{
    public:
        SubClass(const SubClass &sub) : BaseClass(sub){}
};

BaseClass base1();
SubClass sub1();

BaseClass base2(base1);    // 当然OK
SubClass sub2(sub1);    // こっちも
BaseClass base3(sub1);    // あたりまえだけどbase3はBaseClassのインスタンスなのでsub1の複製ではない…


例の最後が気になります。文法上は勿論正しいことなのですが、使い勝手としてはbase3がsub1のコピーとして振舞ってくれることを期待したくなることもあります。例えば数値計算をするときに主役として登場する行列には、スーパークラスの行列に対して、転置行列や部分行列といったサブクラスが存在することになりますが、コピーコンストラクタで行列(転置行列)とやったときに転置行列のコピーが返って来て欲しいと思いませんか?むしろ返ってこないと、いちいちコピーに転置行列(転置行列)とか書かなければならなくなって、わけのわからないことになってしまうと思います。

解決方法を考えてみました。続きをどうぞ。

そこでこういう場合はバックエンドのクラスを作って機能を委譲すると上手くいくと思います。

class BackendBaseClass{
    public:
        virtual *BackendBaseClass copy(){new BackendBaseClass();}
        virtual void some_func(){/* do op1 */;}
};

class BackendSubClass : public BackendBaseClass{
    public:
        *BackendBaseClass copy(){new BackendSubClass();}
        void some_func(){/* do op2 */;}
};

class FrontendBaseClass{
    private:
        BackendBaseClass *delegated;
    public:
        FrontendBaseClass() : delegated(new BackendBaseClass()){}
        FrontendBaseClass(const FrontendBaseClass &frontend) : delegated(frontend.delegated->copy()){}
        void some_func(){delegated->some_func();}
};

class FrontendSubClass : public FrontendBaseClass{
    public:
        FrontendSubClass() : delegated(new BackendSubClass()){}
};

FrontendBaseClass base1();
// base1->some_func() == (do op1)
FrontendSubClass sub1();
FrontendBaseClass base2(sub1);
// base2はFrontendBaseClassのインスタンスだが、委譲先はBackendSubClassになっているので実質的にはsub1のコピー
// つまり、base2->some_func() == sub1->some_func() == (do op2)

なんでこのような話になったかというと、C++で行列のライブラリを練習がてら書いているからです。Boostのライブラリの足元に及ぶくらい(笑)のコードにはしようと思っていますが、なかなか大変です。Expression Templateは、コードが汚くなるのでやらないつもりですが。

23:50 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | この記事をdel.icio.usでブックマーク | トラックバック
このエントリーのトラックバックURL: http://fenrir.naruoka.org/mt/mt-tb.cgi/421
コメント
コメントする









名前、アドレスを登録しますか?
(次回以降コメント入力が楽になります)
  • 匿名でのコメントは受け付けておりません。
  • 名前(ハンドル名可)とメールアドレスは必ず入力してください。
  • メールアドレスを表示されたくないときはURLも必ず記入してください。
  • コメント欄でHTMLタグは使用できません。
  • コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
  • コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。