5

次のコード セグメントを検討してください。

class Window // Base class for C++ virtual function example
     {
       public:
          virtual void Create() // virtual function for C++ virtual function example
          {
               cout <<"Base class Window"<<endl;
          }
     };

     class CommandButton : public Window
     {
       public:
          void Create()
          {
              cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl;
          }
     };

     int main()
     {
        Window *button = new   CommandButton;
        Window& aRef = *button;
        aRef.Create(); // Output: Derived class Command Button - Overridden C++ virtual function
        Window bRef=*button;
        bRef.Create(); // Output: Base class Window

        return 0;
     }

aRefbRefの両方に*buttonが割り当てられますが、2 つの出力が異なるのはなぜですか。参照型と非参照型への代入の違いは何ですか?

4

4 に答える 4

10

スライスの問題が発生しました。

Window bRef   =*button;

ここで bRef は参照ではなくオブジェクトです。派生型を bRef に割り当てると、派生部分が切り捨てられ、CommandButton から構築された Window オブジェクトだけが残ります。

何が起こっているかというと、上記のステートメントで bRef が、コンパイラによって生成されたクラス Window のコピー コンストラクターを使用して作成されているということです。このコンストラクターが行うのは、メンバー要素を RHS から新しく構築されたオブジェクトにコピーすることだけです。クラスにはメンバーが含まれていないため、何も起こりません。

補足: 仮想メンバーを持つクラスには、仮想デストラクタも必要です。

于 2010-12-24T06:41:34.093 に答える
7
  • aRefWindow 静的型ですがCommandButton 動的型があります
  • bRefは単なる型のオブジェクトです(Window部分」はコピーで失われました)CommandButton

これは一般にオブジェクト スライシングとして知られており、通常、基本クラスを抽象化する (純粋な仮想関数を提供することによって) か、コピー不可にする (たとえば、 を使用するboost::noncopyable)ことによって防止されますWindow& aRef = *button;


では、なぜ をbRef.Create()呼び出すのWindow::Createでしょうか。ええと、ただのWindowインbRefしかないので、実際に代替手段はあまりありません。これは本質的に、 a を宣言してそれWindowを呼び出すようなものです。インスタンスからコピーされたCreateという事実は、コピーでその部分が失われたため、無関係です。bRefCommandButtonCommandButton

標準 (10.3/6) を引用して、これをより明確にしようとします。

[注: 仮想関数の呼び出しの解釈は、それが呼び出されるオブジェクトの型 (動的型) に依存しますが、非仮想メンバー関数の呼び出しの解釈は、ポインターの型または型にのみ依存します。そのオブジェクト (静的タイプ)を示す参照(5.2.2)。]

オブジェクトの静的型が動的型と異なるのは、ポインターまたは参照の間接化によってのみです。

于 2010-12-24T06:42:09.697 に答える
2
Window bRef=*button;
bRef.Create(); // Output: Base class Window

の静的タイプと動的タイプbRefWindowのみです。仮想メカニズムは、参照とポインターでのみ機能します。bRef参照またはポインターではないオブジェクトです。

于 2010-12-24T06:41:11.243 に答える
1
 Window bRef=*button;
 bRef.Create(); // Output: Base class Window

これbRefは参照ではありませんbutton(名前を付けただけです)。bRef は、 であるベース サブオブジェクトのみを取得しWindowます。

于 2010-12-24T06:41:20.303 に答える