6

一時的なものを理解しているので、次のコードは機能するはずですが、機能しません。

struct base
{
    virtual~base() {}
    virtual void virt()const=0;
};
struct derived:public base
{
    virtual void virt()const {}
};

const base& foo() {return derived();}

int main()
{
    foo().virt();
    return 0;
}

virt() を呼び出すと、「pure virtual function called」エラーが発生します。それはなぜですか。どうすればよいですか。

4

6 に答える 6

8

関数がステートメントの最後で終了し、return未定義の動作が発生したときに破棄される一時への参照を返しています。

一時的なものへの参照を返すことはできませんbase。値を返すとスライスが発生するため、これを本当に機能させたい場合は、 を返す必要がありますstd::unique_ptr<base>

于 2013-01-23T22:53:13.423 に答える
5

const参照が一時的な寿命を延ばすことを期待しているようです。これが発生しない特定の状況があります。これらの状況の 1 つは、一時的なものを返す場合です。

2 番目のコンテキスト [完全な式の末尾とは異なるポイントで一時変数が破棄される] は、参照が一時変数にバインドされている場合です。参照がバインドされている一時オブジェクト、または参照がバインドされているサブオブジェクトの完全なオブジェクトである一時オブジェクトは、次の例外を除き、参照の存続期間中持続します。

[...]

  • 関数 return ステートメント (6.6.3) の戻り値に一時的にバインドされているものの有効期間は延長されません。一時的なものは、return ステートメントの完全な式の最後で破棄されます。

によって返されるオブジェクトのメンバー関数を呼び出すとfoo()、左辺値から右辺値への変換が必要になり、オブジェクトが無効になる ( type から派生していないbase) ため、未定義の動作が発生します。

glvalue が参照するオブジェクトが型のオブジェクトでTはなく、 から派生した型のオブジェクトでもTない場合、またはオブジェクトが初期化されていない場合、この変換を必要とするプログラムは未定義の動作をします。

于 2013-01-23T22:56:06.670 に答える
3

そのようなオブジェクトへの参照を返すことはできないと思います。foo() が戻るとすぐに、派生() インスタンスは範囲外になります。もつ

base *foo() { return new derived(); }

foo()->virt();

動作するはずです。

于 2013-01-23T22:54:29.153 に答える
0

問題の部分を次のように変更します。

class A {
public:
  const base &foo() { return d; }
private:
  derived d;
};

このように、派生オブジェクトの存続期間は A の存続期間と同じであり、何の問題もありません。

于 2013-01-23T23:12:09.033 に答える
0

呼び出し中にオブジェクトがありません。ローカル オブジェクトが削除されました。見る vtable はありません。試す:

base& foo() { return *new derived(); }
于 2013-01-23T22:56:45.213 に答える
0

一時的な「派生()」オブジェクトがスタックに割り当てられます。オブジェクトのアップキャストと関係があるかもしれません。

const base& foo() { 派生 *d = 新しい派生(); *d を返します。}

私にとってはうまくいきます。

于 2013-01-23T22:57:11.593 に答える