Подтвердить что ты не робот

Конструкторы базового класса, вызывающие С++

#include <iostream>
#include <stdio.h> 
using namespace std;

// Base class
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
      Shape()
      {
    printf("creating shape \n");
      }
      Shape(int h,int w)
      {
     height = h;
         width = w;
         printf("creatig shape with attributes\n");
      } 
   protected:
      int width;
      int height;
};

// Derived class
class Rectangle: public Shape
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
      Rectangle()
      {
     printf("creating rectangle \n");
      }
      Rectangle(int h,int w)
      {
     printf("creating rectangle with attributes \n");
     height = h;
         width = w;
      }
};

int main(void)
{
   Rectangle Rect;

   Rect.setWidth(5);
   Rect.setHeight(7);

   Rectangle *square = new Rectangle(5,5);
   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;
}

Вывод программы приведен ниже

creating shape 
creating rectangle 
creating shape 
creating rectangle with attributes 
Total area: 35

При построении обоих объектов производного класса я вижу, что он всегда является конструктором базового класса по умолчанию, который вызывается. Есть ли причина для этого? И является ли это причиной того, что такие языки, как python, настаивают на явных вызовах конструкторов базового класса, а не на неявные вызовы типа С++?

4b9b3361

Ответ 1

Короткий ответ для этого: "потому что это указывает стандарт С++".

Обратите внимание, что вы всегда можете указать конструктор, отличный от значения по умолчанию, например:

class Shape  {

  Shape()  {...} //default constructor
  Shape(int h, int w) {....} //some custom constructor


};

class Rectangle : public Shape {
  Rectangle(int h, int w) : Shape(h, w) {...} //you can specify which base class constructor to call

}

Конструктор по умолчанию базового класса вызывается только в том случае, если вы не укажете, какой из них вызывать.

Ответ 2

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

Rectangle(int h,int w):
   Shape(h,w)
  {...}

Вызов другого конструктора базового класса.

Ответ 3

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

Когда объекты находятся вне области видимости, он сначала вызовет деструктор производного класса, а затем вызовет деструктор базового класса.

Ответ 4

В С++ компилятор всегда гарантирует, что функции в иерархии объектов будут успешно вызваны. Эти функции являются конструкторами и деструкторами, а иерархия объектов - деревом наследования.

В соответствии с этим правилом мы можем предположить, что компилятор вызовет конструкторы и деструкторы для каждого объекта в иерархии наследования, даже если мы его не реализуем. Для выполнения этой операции компилятор будет синтезировать конструкторы и деструкторы undefined для нас, и мы будем называть их как конструкторы и деструкторы по умолчанию. Затем компилятор будет вызывать конструктор по умолчанию для базового класса и затем вызывает конструктор производного класса.

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

Ответ 5

Представьте себе это так: когда ваш подкласс наследует свойства суперкласса, они не волшебным образом появляются. Вы все равно должны построить объект. Итак, вы вызываете базовый конструктор. Представьте, если класс наследует переменную, которую ваш суперклассовый конструктор инициализирует важным значением. Если мы этого не сделали, ваш код может завершиться неудачно, потому что переменная не была инициализирована.

Ответ 6

Почему вызывается конструктор по умолчанию базового класса? Оказывается, это не всегда так. Любой конструктор базового класса (с разными сигнатурами) может быть вызван из конструктора производного класса. В вашем случае вызывается конструктор по умолчанию, поскольку он не имеет параметров, поэтому он по умолчанию.

Когда производный класс создается, порядок, который вызываются конструкторами, всегда Base → Производится в иерархии. Если мы имеем:

class A {..}
class B : A {...}
class C : B {...}
C c;

Когда c создается, сначала запускается конструктор для A, а затем конструктор для B, а затем конструктор для C.

Чтобы гарантировать этот порядок, когда вызывается конструктор производного класса, он всегда вызывает конструктор базового класса до того, как конструктор производного класса может сделать что-нибудь еще. По этой причине программист может вручную вызвать конструктор базового класса в единственном списке инициализации конструктора производного класса с соответствующими параметрами. Например, в следующем коде конструктор Derived по умолчанию вызовет базовый конструктор Base:: Base (int i) вместо конструктора по умолчанию.

Derived() : Base(5)
{      
}

Если в списке инициализации конструктора производного класса нет такого конструктора, то программа предполагает конструктор базового класса без параметров. Это причина, по которой вызывается конструктор без параметров (т.е. Конструктор по умолчанию).