0

我遇到了这个询问其输出的问题。

#include<iostream>
using namespace std;
class A{
      public:
            int i;
            A(int j=3):i(j){}
};
class B:virtual public A{
      public:
            B(int j=2):A(j){}
};
class C:virtual public A{
      public:
            C(int j=1):A(j){}
};
class D:public B, public C {
      public:
            D(int j=0):A(j), B(j+1), C(j+2){}
};
int main()
{
D d;
cout<<d.i;
return 0;
}

我不明白的事情很少。请澄清这些疑问。我无法谷歌搜索,因为我不知道要搜索什么。

Q1。在代码中使用了参数化构造函数。在冒号(:) 之后我们编写父类的构造函数。如何

A(int j=3):i(j){}

用来?因为我不是一个班级。

Q2。在类 D 中,类的构造函数使用构造函数来初始化基类。但是可以看出,所有的构造函数都只修改了类 A 的变量 i。那么这里的构造函数调用顺序是什么。

我知道当我们不调用父类的构造函数时,它是显式调用的并且顺序是众所周知的,但是当我们像这里这样隐式调用构造函数时会怎样。

Q3。尽管初始化了参数,但我们在构造函数中发送的值似乎有所不同。为什么会这样?

4

4 回答 4

4

A1。:i(j)inA(int j=3):i(j){}是一个初始化列表。初始化列表可以指定如何初始化父类成员变量。(j)是局部变量的初始化器i,其行为类似于局部变量的初始化:int i(j);. (您可能更熟悉int i = j;类似的初始化语法。您不能=在初始化列表中使用该语法。)

A2。虚拟基类总是由最派生类的构造函数专门初始化。SoD的构造函数初始化其A基类,并且当D构造函数调用构造函数时BC这些构造函数不会重新初始化A

A3。语法D(int j=0)不初始化参数。相反,它为参数声明一个默认值,只要您显式传递该参数的值,该默认值就会被忽略。

于 2013-01-04T23:54:21.143 回答
3

ctor-initializer-list包含所有子对象的初始化程序。这意味着基类子对象和成员子对象。

子对象总是按照它们在类定义中出现的顺序进行初始化。将它们放在ctor-initializer-list中的顺序无关紧要(尽管在忽略顺序时将它们放在任何其他顺序中都会令人困惑)。

继承的基子对象构造函数由直接派生的类的构造函数调用......除了虚拟基子对象,它们直接从最派生对象的构造函数调用。虚拟基础子对象是在其他任何东西之前构建的。

没有“正在初始化的参数”之类的东西。这些是默认参数,并且在提供实际参数时会被忽略。

于 2013-01-04T23:27:02.317 回答
0

1)冒号:可以在构造函数中使用给定参数调用成员变量的构造函数:

public:
        int i;
        A(int j=3):i(j){}

意味着A' 的成员i将调用其构造函数j作为参数。

2) 子对象将按照它们在类定义中出现的顺序进行初始化

class D:public B, public C

3)它们没有被初始化,它们被赋予了默认参数。

于 2013-01-04T23:33:56.503 回答
0

Q1:构造函数中函数签名和函数体左括号之前的代码称为初始化列表。

初始值设定项列表的语法是类的成员变量的列表以及相应的初始值。初始值在括号中。成员变量用逗号分隔。第一个变量出现在冒号之后。

初始化列表还可以包含基类的构造函数,这是 B 和 C 类所做的。您的“A”类只是使用初始化成员变量的形式。

Q2:要查找构造函数的执行顺序,请输入一些打印语句。它将帮助您了解构建顺序。还要放入一个析构函数并将打印语句也放入其中。在这个问题上,我不能为你做所有的功课。:)

Q3:我猜参数被初始化是指默认参数?如果实际将值传递给函数,则始终会覆盖默认参数。

于 2013-01-04T23:37:37.240 回答