2010-12-24 3 views
5

Рассмотрим следующий фрагмент кода:поведение C++ 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; 
    } 

Оба Ареф и СДНИМ получить назначения * Кнопка, но почему два вывода различны. В чем разница между присвоением типа Reference и non Reference типа?

ответ

10

Вы столкнулись с проблемой нарезки.

Window bRef =*button; 

Здесь bRef - это не ссылка, а объект. Когда вы назначаете производный тип на bRef, вы нарезаете производную часть, оставив вам только объект Window, построенный с помощью CommandButton.

Что происходит, так это то, что bRef создается в вышеупомянутом выражении с использованием созданного компилятором конструктора копии для окна класса. Все, что делает этот конструктор, это элементы-члены-копии из RHS для вновь созданного объекта. Поскольку класс не содержит членов, ничего не происходит.

На стороне примечание: класс с виртуальными членами также должен иметь виртуальный деструктор.

+0

Итак, с этим конструктором копии позднего связывания просто не происходит, не так ли? –

+0

Наводчик: последнее связывание здесь не имеет отношения. Вы создаете новый статически типизированный объект, а не динамически типизированный объект (для этого вам нужна ссылка или указатель). –

+0

виртуальный или защищенный деструктор. Во многих конструкциях функции-члены называются полиморфными без удаления полиморфно. –

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

Статическая, а также динамический тип bRef только Window. Виртуальный механизм работает только со ссылками и указателями. bRef - объект, не являющийся ссылкой или указателем.

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

Здесь bRef не ссылка на button (вы только что назвали его так). bRef получает только базовый подобъект, который равен Window.

+0

Но каков эффект от этого задания, которое я выполняю. Так как * кнопка была инициализирована с помощью CommandButton, не следует ли это компилировать ошибку? –

+0

№ Класс вашего окна имеет конструктор копирования Window (const Window &). Поскольку CommandButton - это Window, он может быть аргументом для этого конструктора копирования. – cgmb

+0

@ Slavik81: Да, так? Как это делает недействительным то, что я сказал? – Nawaz

7
  • aRef имеет Windowстатический типа, но CommandButtonдинамического типа
  • bRef просто объект типа Window (CommandButton'часть' была потерян в копии)

Это общеизвестно как object slicing a d обычно предотвращается путем создания базовых классов либо абстрактными (путем предоставления чистой виртуальной функции), либо не копируемыми (например, с использованием boost::noncopyable), так как либо решение сделает код не скомпилированным в строке Window& aRef = *button;.


Теперь, почему bRef.Create() вызов Window::Create? Ну, есть не более, чем Window в bRef, так что на самом деле не так много альтернативы. Это по существу похоже на объявление Window и вызов Create на нем: факт, что bRef был скопирован из экземпляра CommandButton, не имеет значения, поскольку часть CommandButton была потеряна в копии.

Я попытаюсь сделать это более понятным, указав стандарт (10.3/6):

[Примечание: интерпретация вызова виртуальной функции зависит от типа объекта, для которого оно называется (динамический тип), в то время как интерпретации вызова функции нежирного элемента зависит от типа указателя или . ]

Только с помощью указателя или ссылки может статический тип объекта отличается от его динамического типа.