私は自分の会社のために構築したプロジェクトのクラス構造をいくつか持っています。ある時点で、派生オブジェクトの「通常は望ましくない」スライスが実際に私のコードを効率的にするのを見てきました。観察してください:
class Base {
private:
int myType; //some constant here
public:
Base(): myType(1)
{
if(someTest())
{
myTest = 0; // signifies that this object is not working well for me
} // if the test succeeds, now I know this is a TYPE1 object
}
virtual bool someTest() { /* does make some validation tests */ }
int GetMyType() { return myType; }
// some more virtual functions follow
}
class Derived: public Base {
public:
Derived() : Base()
{
if( someTest() /*calls the derived*/ )
{
myType =2; // signifies that this is a TYPE2 object
/* Do something more*/
}
}
virtual bool someTest() { /* does make OTHER validation tests */ }
}
ここで、Derived の someTest() が失敗した場合、これは、オブジェクトが実際には Base タイプ (myType = 1) または障害のあるオブジェクト (myType =0) であることを示しています。これらはコンストラクターにあり、例外処理 (組み込みシステム) を使用できないため。私はこれについて考えました:
{
// this is the object holder test block
// there is some latch - Base* - above = let's call it "ObjectHolder"
extern Base* ObjectHolder;
Derived * deriv = new Derived();
int dType = deriv->GetMyType() ;
if( dType == 1) // if test at base succeded but the one in derived failed
Base = & static_cast<Base> (*deriv); // specifically slice the object
else if(dType =2)
Base = deriv;
else
delete deriv; // this is a TYPE0 - nonworking- object so don't latch it
// use other implemented methods to do work ...
}
では、なぜこのようなデザインになったのでしょうか。さて、クラスを設計しているうちに、「Base」(type 1) と「Derived」(type 2) のクラスの内部動作のメソッドが異なるため (さらに、type 3,4,5 の可能性がある..)内部も異なるオブジェクト)、およびすべてのメソッドを作成して「if-then-else」でチェックしたくなかったため。私はそのような設計を行い、異なるメソッドを仮想化して、(ポリモーフィズムのおかげで) 正しく呼び出すことができるようにし、共通のメソッドをいくつかの基本クラスに置くことができると考えました。
しかし今、最初に、その奇妙な構文 ( & static_cast < Base > *deriv ) が正しいかどうかはわかりません (テストされ、機能しているように見えましたが、これが運によるものではないことを確認したいだけです)。第二に、これがこれを達成するための「推奨される方法」であるかどうかはわかりません-この構文がメモリリークなどを引き起こす可能性があると思います...
問題をより明確にするために、コードを少し変更しました (構文も修正しました)。
さて、 &(static_cast(*deriv)) は誤ったアプローチであるため、Base クラスでのチェックをバイパスする「コピー コンストラクター」を作成できるかどうかを考えていました (これが、実際にこれらのものを試す理由です。場合によってはそのテストを実行したくない)。以下のように:
class Base {
// other stuff is like above
// cc:
Base(const Base &other) : myType(other.myType)
{
// no test is performed here!
}
// like other one above
}
これを書いたので、テストブロックでそれを行うことができると思います:
{
// the code above
if( dType == 1) // if test at base succeded but the one in derived failed
Base = new Base(*deriv); // specifically slice the object with cc
// code goes on ...
}
これはどうですか?