C ++对象引用的行为

时间:2010-12-24 06:35:53

标签: c++ polymorphism virtual-functions object-reference

考虑以下代码段:

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

aRef bRef 都会被分配 *按钮,但为什么两个输出会有所不同。 分配参考类型和非参考类型有什么区别?

4 个答案:

答案 0 :(得分:10)

您遇到了切片问题。

Window bRef   =*button;

这里bRef不是引用而是对象。当您将派生类型分配到bRef上时,您正在对派生部分进行切片,只留下一个由CommandButton构造的Window对象。

正在发生的事情是,使用编译器生成的类Window的复制构造函数在上面的语句中创建了bRef。所有这些构造函数都是将成员元素从RHS复制到新构造的对象。由于该课程不包含任何成员,因此没有任何事情发生。

旁注:具有虚拟成员的类也应该有一个虚拟析构函数。

答案 1 :(得分:7)

  • aRefWindow 静态类型,但CommandButton 动态类型
  • bRef只是Window类型的对象( CommandButton '部分'在副本中丢失)< / LI>

这通常被称为object slicing,它通常通过使基类抽象(通过提供纯虚函数)或不可复制(例如使用boost::noncopyable)来防止,因为任何一种解决方案都会使代码无法在第Window& aRef = *button;行编译。


现在,为什么bRef.Create()拨打Window::Create?好吧,Window中只有bRef,所以实际上没有太多选择。这基本上就是声明Window并在其上调用CreatebRefCommandButton实例复制的事实无关紧要,因为CommandButton部分是丢失在副本中。

我会试着通过引用标准(10.3 / 6)来使这个更清楚:

  

[注:解释电话   虚函数取决于   它所对象的类型   叫(动态类型),而   解释一个电话   非虚拟成员函数取决于   仅限指针的类型或   表示该对象的引用(   静态类型)(5.2.2)。 ]

只有通过指针或引用间接,对象的静态类型才能与其动态类型不同。

答案 2 :(得分:2)

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

bRef的静态和动态类型仅为Window。虚拟机制仅适用于引用和指针。 bRef是一个对象而不是引用或指针。

答案 3 :(得分:1)

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

此处bRef不是button的引用(您只是将其命名为)。 bRef只获取Window的基础子对象。