1

私は、次のアプローチが a) 合法であり、b) 道徳的であるかどうか (およびその理由) を尋ねています。C++03 に重点を置いて質問していますが、C++11 に関するメモも歓迎します。アイデアは、それ自体がデフォルトで構築可能である可能性のある派生クラスが愚かなB::B(int foo) : A(foo) {}コンストラクターを実装するのを防ぐことです。

class Base {
  private:
    int i;
    Base(int i) : i(i) {}
  protected:
    Base() {}
  public:
    static Base* create(int i);
};
class Derived : public Base {
};

Base* Base::create(int i) {
  Derived* d = new Derived();
  Base* b = static_cast<Base*>(d);
  delete b;
  new(b) Base(i);
  return d;
}

私の腸は、ここで何かが怪しいと言っています。いずれかのDerivedクラスがそのコンストラクターでメンバーにアクセスする場合Base、私は別の場所に行きたいと思いますが、それ以外の場合、アプローチが悪い正当な理由を見つけるのに苦労します.

とにかく、これが許容できるアプローチだと思う場合、参照メンバー (のようなものint& Base::j) をどのように処理しますか?

注:これは、 C++03 でコンストラクターの継承を偽造するにはどうすればよいですか?へのフォローアップの質問です。.


編集:質問を投稿するときに気が散っていたに違いありません。もちろん、delete b私が意味するのではなくb->~Base()。低血糖のせい!

4

2 に答える 2

3

コードが正しくなく、未定義の動作がトリガーされます。Baseクラスには仮想デストラクタがありません。これは、が未定義動作を引き起こすことを意味しますdelete b

呼び出しのUBの理由は、派生リソースを解放deleteしないという事実(コードの目的のようです)から、割り当てられたメモリを解放しようとするという事実まで、さまざまです。両方のオブジェクトのレイアウトに応じて、機能するかどうか。メモリの割り当て解除に失敗した場合、おそらくクラッシュします。配置に成功した場合、次の行の新しい呼び出しは、すでに解放されているメモリ内のオブジェクトを初期化しようとします...

コードを(割り当て解除の問題を回避しようとして)次のように変更した場合でも、次のようになります。

Base* Base::create(int i) {
   Derived *d = new Derived;
   Base * b = static_cast<Base*>(d);
   b->~Base();                       // destruct, do not deallocate
   new (b) Base(i);
   return d;
}

未定義動作の特定のソースが存在deleteしないためになくなった場合でも、コードは未定義動作のままです(おそらく、言及することすらできないほど多くの方法で)。デストラクタの呼び出しがまだUBである場合、そうでない場合でも、型を再作成したという事実は、そのオブジェクトの動的ディスパッチがおそらくオブジェクトをオブジェクトではなくオブジェクトと見なすことを意味します(sの場合、実行時型情報を指すものは、ではなく、を参照します)BaseBaseDerivedvtablevptrBaseDerived

そして、おそらく他に2つか3つの問題が発生する可能性があり、今は考えられません...

于 2011-11-03T15:02:56.053 に答える
1

delete bs デストラクタを呼び出すだけでなくBase、によって返されたメモリの割り当てを解除し、 s デストラクタnewを呼び出しDerivedます [仮想デストラクタを使用することを意図していると仮定するとBase...非仮想にすることを意図した場合、動作はそもそも定義されていません]。つまり、その後の配置 new の使用はBase、もはや有効ではないまったく新しいオブジェクトをメモリ内に構築していることを意味し、Derived以前に破棄した部分を置き換えることは決してありません。要するに、あなたがしたことは何も正しい行動に近づくことすらありません。

率直に言って、あなたが何をしようとしているのかわかりません...Derived引数を転送するだけでなく、デフォルトで構築する必要があるのはなぜですか? それは愚かではなく、物事が行われる方法です。

于 2011-11-03T15:06:40.447 に答える