C++ 调用基类构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15777635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:45:53  来源:igfitidea点击:

C++ calling base class constructors

c++objectinheritance

提问by liv2hak

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

The output of the program is given below

程序的输出如下

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

When constructing both the derived class objects I see that it is always by default the base class constructor that is called first. Is there a reason for this? Is this the reason why languages like python insist on explicit calls of base class constructors rather than implicit calls like C++?

在构造两个派生类对象时,我看到默认情况下总是首先调用基类构造函数。是否有一个原因?这就是为什么像 python 这样的语言坚持显式调用基类构造函数而不是像 C++ 这样的隐式调用的原因吗?

回答by maditya

The short answer for this is, "because that's what the C++ standard specifies".

对此的简短回答是,“因为这是 C++ 标准指定的”。

Note that you can always specify a constructor that's different from the default, like so:

请注意,您始终可以指定与默认值不同的构造函数,如下所示:

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

}

The default constructor of the base class is called only if you don't specify which one to call.

仅当您未指定调用哪一个时,才会调用基类的默认构造函数。

回答by rerun

The default class constructor is called unless you explicitly call another constructor in the derived class. the language specifies this.

除非您显式调用派生类中的另一个构造函数,否则将调用默认类构造函数。语言指定了这一点。

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

Will call the other base class constructor.

将调用另一个基类构造函数。

回答by taocp

When objects are constructed, it is always first construct base class subobject, therefore, base class constructor is called first, then call derived class constructors. The reason is that derived class objects contain subobjects inherited from base class. You always need to call the base class constructor to initialze base class subobjects. We usually call the base class constructor on derived class's member initialization list. If you do not call base class constructor explicitly, the compile will call the default constructor of base class to initialize base class subobject. However, implicit call on default constructor does not necessary work at all times (for example, if base class defines a constructor that could not be called without arguments).

构造对象时,总是先构造基类子对象,因此,先调用基类构造函数,再调用派生类构造函数。原因是派生类对象包含从基类继承的子对象。您总是需要调用基类构造函数来初始化基类子对象。我们通常在派生类的成员初始化列表上调用基类构造函数。如果不显式调用基类构造函数,编译器会调用基类的默认构造函数来初始化基类子对象。但是,对默认构造函数的隐式调用并非始终都必须起作用(例如,如果基类定义了一个没有参数就无法调用的构造函数)。

When objects are out of scope, it will first call destructor of derived class,then call destructor of base class.

当对象超出范围时,它会先调用派生类的析构函数,然后调用基类的析构函数。

回答by Validus Oculus

In c++, compiler always ensure that functions in object hierarchy are called successfully. These functions are constructors and destructors and object hierarchy means inheritance tree.

在 c++ 中,编译器始终确保成功调用对象层次结构中的函数。这些函数是构造函数和析构函数,对象层次结构意味着继承树。

According to this rule we can guess compiler will call constructors and destructors for each object in inheritance hierarchy even if we don't implement it. To perform this operation compiler will synthesize the undefined constructors and destructors for us and we name them as a default constructors and destructors.Then, compiler will call default constructor of base class and then calls constructor of derived class.

根据这个规则,我们可以猜测编译器会为继承层次结构中的每个对象调用构造函数和析构函数,即使我们没有实现它。为了执行这个操作,编译器会为我们合成未定义的构造函数和析构函数,我们将它们命名为默认构造函数和析构函数。然后,编译器将调用基类的默认构造函数,然后调用派生类的构造函数。

In your case you don't call base class constructor but compiler does that for you by calling default constructor of base class because if compiler didn't do it your derived class which is Rectangle in your example will not be complete and it might cause disaster because maybe you will use some member function of base class in your derived class. So for the sake of safety compiler always need all constructor calls.

在您的情况下,您不调用基类构造函数,但编译器通过调用基类的默认构造函数为您执行此操作,因为如果编译器不这样做,则您的示例中的派生类 Rectangle 将不完整,并且可能会导致灾难因为也许您会在派生类中使用基类的某些成员函数。所以为了安全起见,编译器总是需要所有的构造函数调用。

回答by Tris

Why the base class' default constructor is called? Turns out it's not always be the case. Any constructor of the base class (with different signatures) can be invoked from the derived class' constructor. In your case, the default constructor is called because it has no parameters so it's default.

为什么调用基类的默认构造函数?事实证明并非总是如此。基类的任何构造函数(具有不同的签名)都可以从派生类的构造函数中调用。在你的情况下,默认构造函数被调用,因为它没有参数,所以它是默认的。

When a derived class is created, the order the constructors are called is always Base -> Derived in the hierarchy. If we have:

创建派生类时,调用构造函数的顺序在层次结构中始终为 Base -> Derived。如果我们有:

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

When c is create, the constructor for A is invoked first, and then the constructor for B, and then the constructor for C.

创建 c 时,首先调用 A 的构造函数,然后是 B 的构造函数,然后是 C 的构造函数。

To guarantee that order, when a derived class' constructor is called, it always invokes the base class' constructor before the derived class' constructor can do anything else. For that reason, the programmer can manually invoke a base class' constructor in the only initialisation list of the derived class' constructor, with corresponding parameters. For instance, in the following code, Derived's default constructor will invoke Base's constructor Base::Base(int i) instead of the default constructor.

为了保证这个顺序,当派生类的构造函数被调用时,它总是在派生类的构造函数可以做任何其他事情之前调用基类的构造函数。因此,程序员可以在派生类的构造函数的唯一初始化列表中手动调用基类的构造函数,并带有相应的参数。例如,在以下代码中,Derived 的默认构造函数将调用 Base 的构造函数 Base::Base(int i) 而不是默认构造函数。

Derived() : Base(5)
{      
}

If there's no such constructor invoked in the initialisation list of the derived class' constructor, then the program assumes a base class' constructor with no parameters. That's the reason why a constructor with no parameters (i.e. the default constructor) is invoked.

如果派生类的构造函数的初始化列表中没有调用这样的构造函数,则程序假定基类的构造函数没有参数。这就是调用没有参数的构造函数(即默认构造函数)的原因。

回答by Thomas Hobohm

Imagine it like this: When your sub-class inherits properties from a super-class, they don't magically appear. You still have to construct the object. So, you call the base constructor. Imagine if you class inherits a variable, which your super-class constructor initializes to an important value. If we didn't do this, your code could fail because the variable wasn't initialized.

想象一下:当您的子类从超类继承属性时,它们不会神奇地出现。您仍然必须构造对象。因此,您调用基本构造函数。想象一下,如果您的类继承了一个变量,您的超类构造函数将其初始化为一个重要值。如果我们不这样做,您的代码可能会因为变量未初始化而失败。