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

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は、コードが汚くなるのでやらないつもりですが。

August 30, 2005 23:50 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク

コメント

コメントする