Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behavior of C++ Object Reference

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?

like image 384
Shamim Hafiz - MSFT Avatar asked Dec 24 '10 06:12

Shamim Hafiz - MSFT


3 Answers

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.

like image 167
Martin York Avatar answered Oct 13 '22 20:10

Martin York


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.

like image 2
Prasoon Saurav Avatar answered Oct 13 '22 20:10

Prasoon Saurav


  • 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.

like image 7
icecrime Avatar answered Oct 13 '22 20:10

icecrime