Поведение C ++ Object Reference - PullRequest
       79

Поведение C ++ Object Reference

5 голосов
/ 24 декабря 2010

Рассмотрим следующий сегмент кода:

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 ]

10 голосов
/ 24 декабря 2010

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

Window bRef   =*button;

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

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

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

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

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


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

Я попытаюсь прояснить это, цитируя стандарт (10.3 / 6):

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

Статический тип объекта может отличаться только от указателя или косвенной косвенной ссылки.

2 голосов
/ 24 декабря 2010
Window bRef=*button;
bRef.Create(); // Output: Base class Window

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

1 голос
/ 24 декабря 2010
 Window bRef=*button;
 bRef.Create(); // Output: Base class Window

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...