简体   繁体   English

C ++继承初始化列表

[英]C++ inheritance initializer list

I am very new to C++ , but I come from a Java background so I understand most of the OOP concepts. 我是C++新手,但我来自Java背景,所以我理解大多数OOP概念。 I am reading through an introductory guide and I came across this example: 我正在阅读介绍性指南,我遇到了这个例子:

[Foo.H] 
class A
{
    public:
       A(int something);
};

class B : public A
{
    public:
       B(int something);
};

[Foo.C] 
#include "Foo.H"

A::A(int something)
{
    printf("Something = %d\n", something);
}

B::B(int something) : A(something)
{
}

Is it correct to assume that by passing A(something) to the initializer list of B::B(int something) it is similar to the super keyword in java -- aka, it will execute A::A(int something) 's code? 假设通过将A(something)传递给B::B(int something)的初始化列表是正确的,它类似于java中的super关键字 - 也就是说,它将执行A::A(int something) '代码? Also, why do I only call A(something) instead of A::A(something) from the initalizer list? 另外,为什么我只从initalizer列表中调用A(something)而不是A::A(something)

Basically I am asking: is the above equivalent to this: 基本上我要问的是:以上是否等同于此:

B::B(int something)
{
    A::A(something)
}

Let me expand why I am confused. 让我来解释为什么我感到困惑。

If I were to use: 如果我使用:

B::B(int something) : A(something)
{
    int x = 5;
    printf("x = %d", x);
}

And call the code via 并通过调用代码

B::B(7);

Would this print out x = 5 or something = 7 first? 这会首先打印x = 5或者something = 7吗? And why would it execute in this order? 为什么它会按此顺序执行?

I am just a little confused as to the syntax which is making it hard to grasp and visualize the inheritance happening in even this simple example. 我只是对语法有点困惑,这使得很难掌握和可视化即使在这个简单的例子中发生的继承。

Yes, A(something) passes that value much like super . 是的, A(something)传递的价值就像super You don't have to use A::A because the language automatically injects the base class name into the child class. 您不必使用A::A因为该语言会自动将基类名称注入子类。

It's not however equivalent to 但它并不等同于

B::B(int something)
{
    A::A(something)
}

because that's not legal code. 因为那不是合法的代码。 You can only select which parent constructor to call in the initializer list. 您只能在初始化列表中选择要调用的父构造函数。

As for your question about printing...did you try it? 至于你关于印刷的问题......你试过吗? You'll see that the parent something= prints first followed by x= . 你会看到父something=先打印后跟x=

no they are not equivalent 不,他们不等同

constructor of subclass will call the default constructor of their parent unless you explicitly tell it otherwise in the initializer list. 除非你在初始化列表中明确地告诉它,否则子类的构造函数将调用其父类的默认构造函数。

B::B( int something ) {} will call A::A() implicitly and if A does not have a default constructor it will not compile. B::B( int something ) {}将隐式调用A::A() ,如果A没有默认构造函数,则不会编译。

B::B(int something)
{
    A::A(something)
}

what this does is that it tries to call A::A() implicitly in the initializer list, then call A::A(something) , as you know it will not compile given A does not have default constructor. 这样做是因为它试图在初始化列表中隐式调用A::A() ,然后调用A::A(something) ,因为你知道它不会编译给定A没有默认构造函数。

so if you want to call different parent constructor the only way is to do it is in the initializer list namely 所以如果你想调用不同的父构造函数,那么唯一的方法就是在初始化列表中

B::B(int something) : A(something) {}
A::A(int something)
{
    printf("Something = %d\n", something);
}

This is the constructor for B. The first thing a constructor does is construct it's base classes (in the order declared in the class, not in the order of the constructor), and then construct the member objects (in the order declared in the class, not in the order of the constructor), and then it executes the body (the code in {} ). 这是B的构造函数。构造函数所做的第一件事是构造它的基类(按照在类中声明的顺序,而不是构造函数的顺序),然​​后构造成员对象(按类中声明的顺序) ,而不是按构造函数的顺序),然​​后它执行主体( {}的代码)。 The reason it does this is because a B is an A object, so it must be a complete A before it can even start to be a B object. 这样做的原因是因为B 一个A对象,所以它必须是一个完整的A才能开始成为一个B对象。 And all members must be fully constructed before executing any member function's code, or else bad things could happen. 并且在执行任何成员函数的代码之前必须完全构造所有成员,否则可能发生不好的事情。 So both base classes and members must be constructed before the constructor body can begin. 因此,必须在构造函数体开始之前构造基类和成员。

If you want to change how a base class or member is initialized (to pass an integer instead of default constructing for instance), you may put it in the initializer list: 如果要更改基类或成员的初始化方式(例如,传递整数而不是默认构造),可以将其放在初始化列表中:

B::B(int something) : A(something)
{
    int x = 5;
    printf("x = %d", x);
}

You don't have to qualify the name of A 's constructor, because we're already in the context of the object B , and B already knows about A . 您不必限定A的构造函数的名称,因为我们已经在对象B的上下文中,并且B已经知道A

B::B(int something)
{
    A::A(something)
}

This code is invalid, because B will construct it's A object before executing the body in {} . 此代码无效,因为B将在{} 执行主体之前构造它的A对象。 Since A was already constructed, calling A::A in the body makes no sense, and the compiler will diagnose this. 因为A已经建立,调用A::A在体内是没有意义的,编译器会诊断此。

B::B(int something) : A(something)
{
    int x = 5;
    printf("x = %d", x);
}

As mentioned before, when constructing B, it constructs the base classes first, then members, then executes the body. 如前所述,在构造B时,它首先构造基类,然后构造成员,然后执行主体。 Therefore you will see 所以你会看到

something = 7
x = 5

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM