как называются функции не полностью построенных объектов? - PullRequest
2 голосов
/ 13 сентября 2011

создание объекта с использованием конструктора и наряду с теми вызывающими функциями объекта, который строится:

class A
{
  public:
        A()
        {
        this->show();
        }   

        void show()
        {
        cout<<"show called!";
        }
};

и теперь я создаю объект в main(), как показано ниже:

int main()
{
    A a;
    int xy;
    cin>>xy;
    return 0;
}

я сомневаюсь, что когда я создаю объект с помощью конструктора, как я могу вызывать функцию объекта, пока объект не полностью создан?

вызовы виртуальных функций:

class A
{
  public:
        A()
        {

        }   

       virtual void show()
        {
        cout<<"show called!";
        }
};
class B:public A
{
      public: 
              B()
              {
                    A *a=this;
                    a->show();

                    }
             void show()
             {
                  cout<<"derived show";
                  }

      };


int main()
{
    A a;
    B b;
    int xy;
    cin>>xy;
    return 0;
}

нормально работает с выводом: derived show

Ответы [ 6 ]

4 голосов
/ 13 сентября 2011

Можно вызывать виртуальные функции и нестатические функции-члены:

См. Раздел 12.7 http://www.open -std.org / jtc1 / sc22 / wg21 / docs /apers / 2011 / n3242.pdf :

4 Функции-члены, включая виртуальные функции (10.3), могут быть вызваны во время строительства или разрушения (12.6.2).

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

Когда виртуальная функция вызывается прямо или косвенно из конструктор (включая mem-initializer или инициализатор фигурной скобки или равный для нестатического члена данных) или из деструктор, и объект, к которому применяется вызов, является объектом в стадии строительства или уничтожения, вызываемая функция определяется в собственном классе конструктора или деструктора или в одном из его оснований, но не функции, переопределяющей его в классе, производном от класс конструктора или деструктора, или переопределение его в одном из другие базовые классы самого производного объекта (1.8).

Я интерпретирую вышеприведенный абзац как высказывание, что вызываемые виртуальные функции не будут ни в каком производном классе. Это имеет смысл, потому что на этом этапе на этапе выполнения любой конструктор в производном классе не будет начинать выполнение.

Кроме того, в части 1 вводится ограничение на использование нестатических элементов после начала строительства. В вашем примере участники вызываются после начала строительства, поэтому вы не нарушаете часть 1:

1 Для объекта с нетривиальным конструктором, ссылаясь на любой нестатический член или базовый класс объекта перед конструктором начинает выполнение результатов в неопределенном поведении.

1 голос
/ 13 сентября 2011

Надо подумать о том, какие части объекта создаются в тот момент, когда вы вызываете show ()?

Поскольку вы вызываете show () из тела вашего конструктора (а не, например, из списка инициализатора конструктора), вы можете быть уверены, что все переменные-члены объекта A уже созданы (поскольку это происходит до того, как тело конструктора выполняется).

Что может сбить вас с толку, так это если бы show () был виртуальным методом, и A :: A () вызывался из конструктора подкласса A. В этом случае вы можете захотеть вызвать show () B :: show (), но этого не произойдет, потому что vtable для B еще не был настроен (вместо этого вы бы вызвали A :: show () или выручили бы программу, если A :: show () был чисто виртуальный метод)

1 голос
/ 13 сентября 2011

Этот код полностью легален.Вы можете вызывать методы в конструкторе класса.

Все константы (из списка инициализации) уже инициализированы, и все конструкторы базового класса вызываются.

Однако Вы не должны вызывать виртуальные методы вконструктор.См. Скотт Мейерс объяснение этого ограничения.

0 голосов
/ 13 сентября 2011

я сомневаюсь, что когда я создаю объект с помощью конструктора, то как я могу вызывать функцию объекта, пока объект не полностью построен?

то, что происходит в вашем примере, прекраснодо тех пор, пока вы инициализируете, где вы должны (список инициализации).вы используете статическую диспетчеризацию для объекта, который имеет инициализированные элементы (в частности, A не имеет таких переменных для инициализации).

что тогда недопустимо?

  • не инициализирует ваши элементыправильно, или используя их, прежде чем они действительно инициализируются.добавьте в список инициализации, не используя this.
  • , используя динамическую диспетчеризацию из тела вашего конструктора (или инициализатора).Ваш объект не полностью построен.
  • необычно, вы также можете попытаться привести его к подклассу из конструктора.
0 голосов
/ 13 сентября 2011

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

Поля «создаются» при создании экземпляра объекта перед запуском конструктора. Однако для них не установлены значения. Итак, если ваш конструктор вызывает какие-либо методы ДО того, как поля инициализируются разумными значениями, то вы будете испытывать некоторое неопределенное поведение.

По возможности, если вам необходимо вызвать метод внутри конструктора, обязательно инициализируйте как можно больше полей разумными значениями.

0 голосов
/ 13 сентября 2011

Вы вызываете функцию в частично сконструированном объекте, что может привести к ошибочному поведению, если такая функция имеет дело с членами класса и тому подобным. Я не уверен, вызывает ли это неопределенное поведение или нет, но я не думаю, что это хорошая практика. И ситуация ухудшается с наследованием и виртуальными функциями!

В вашем примере show может быть объявлено как static, и при вызове его не будет никакого риска.

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