Behavior of C++ Object Reference

谁说胖子不能爱 提交于 2019-12-10 14:39:08

问题


Consider the following code segment:

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;
     }

Both aRef and bRef get assigned *button, but why are the two output different. What is the difference between assigning to Reference type and non Reference type?


回答1:


You have encountered the slicing problem.

Window bRef   =*button;

Here bRef is not a reference but an object. When you assign a derived type onto bRef you are slicing the derived part off leaving you with just a Window object constructed form a CommandButton.

What is happening is that bRef is created in the above statement using the compiler generated copy constructor for the class Window. All this constructor does is copy member elements from the RHS to the newly constructed object. Since the class contains no members nothing is happening.

On a side note: A class with virtual members should also have a virtual destructor.




回答2:


  • aRef has Window static type but CommandButton dynamic type
  • bRef is simply an object of type Window (the CommandButton 'part' was lost in the copy)

This is commonly known as object slicing and it usually prevented by making base classes either abstract (by providing a pure virtual function) or non copyable (for example using boost::noncopyable), because either solution would make the code fail to compile on line Window& aRef = *button;.


Now, why does bRef.Create() call Window::Create ? Well, there is nothing more than a Window in bRef so there really isn't much of an alternative. This is essentially like declaring a Window and calling Create on it : the fact that bRef was copied from a CommandButton instance is irrelevant because the CommandButton portion was lost in the copy.

I'll try to make this clearer by quoting the standard (10.3/6) :

[Note: the interpretation of the call of a virtual function depends on the type of the object for which it is called (the dynamic type), whereas the interpretation of a call of a nonvirtual member function depends only on the type of the pointer or reference denoting that object (the static type) (5.2.2). ]

Only through a pointer or reference indirection can the static type of an object differ from its dynamic type.




回答3:


Window bRef=*button;
bRef.Create(); // Output: Base class Window

The static as well as dynamic type of bRef is Window only. Virtual mechanism works only with references and pointers. bRef is an object not a reference or a pointer.




回答4:


 Window bRef=*button;
 bRef.Create(); // Output: Base class Window

Here bRef is not the reference to button (you just named it so). bRef gets only the base subobject which is Window.



来源:https://stackoverflow.com/questions/4524639/behavior-of-c-object-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!