2
struct Abstract{
    virtual void methodA() = 0;
};

struct Test : public Abstract{
    virtual void methodA(){
        printf("Test message");
    }
};

class Foo{
    Abstract* abs; //I made it this way so that an instance of Foo 
                   //can easily switch between any class that implements 
                   //Abstract
public:
    virtual ~Foo(){
        delete abs; //free abs
    }

    void setAbs(Abstract* a){
        abs = a; //is there any other way to do this?
    }

    void changeAbs()//method to switch abs

    void show(){
        abs->methodA();
    }
};

int main(){
    Test *test = new Test();
//    Test test; //local instantiation will throw a segmentation fault
               //because abs is freed in the desctructor of Foo
    Foo foo;
    foo.setAbs(test);
    foo.show();

//    delete test; //using a pointer is fine unless freed
    return 0;
}

私の懸念は次のとおりです。

  1. デストラクタでabsを解放せず、ユーザーがAbstractを実装するオブジェクトを解放するのを忘れた場合、またはユーザーがこの方法setAbs(new Test())で解放した場合、リークが発生します。

  2. デストラクタでabsを解放すると、ユーザーがローカルでTestをインスタンス化するか、ポインタを使用して最終的に自分で削除すると、セグメンテーション違反が発生します。

  3. Abstract abs抽象クラスであるため、許可されていません

setAbs()を次のようなものに変更したいと思います。

void setAbs(Abstract* a){
    abs = new Abstract(*a); //but copying like a normal class doesn't work on abstract classes
}  

私の質問は、渡された引数のコピーを作成するようにsetAbs()を実装する他の方法はありますか?

他に方法がない場合は、ユーザーの仕事を解放するだけにします。

4

1 に答える 1

4

ここでの根本的な問題は、誰がこの記憶を所有しているのかを明確にしていないということです。

クラスがそれを所有している場合は、デストラクタで割り当てを解除しても安全です。まあ、あなたがそれを書いた方法ではなく、理論的には。三つのルールを読んでください。

クラスがポインタを所有していない場合は、割り当てを解除しないでください。割り当てを解除するのはあなたではないので、それを使用してこれ以上実行しないでください。

メモリを処理する安全な方法は、誰が何に対して責任があるかについて暗黙的に契約を強制することです。ユーザーが先に進んでdeleteポインターを入力した場合は、停止するように指示します。それは彼らの仕事ではありません。std::unique_ptrポインタとget()関数を使用して同じことを行うことができます。クラスはあなたを止めません、どうしてそれができますか?自分の足を撃ち落としても構いません。RTFM。

と言えばstd::unique_ptr...なぜそれを使用しないのですか(またはstd::shared_ptr適切な場合)?これは解決された問題であり、ここで独自の解決策を考え出す必要はありません。

于 2013-03-07T04:10:51.253 に答える