0

我很想了解这个是如何工作的!

例如,如果我有此代码

class myclass

{
    public :

        int a;

        myclass(){a=0; cout<<"first"<<endl;}

        myclass(int i){a=i;cout<<"second"<<endl;}

        ~myclass(){cout<<a<<endl;}

};

class yourclass:protected myclass

{
    int x;
    myclass m1;

    public:

        myclass m2;

        yourclass (int i): m2(3),myclass(i){x=i; a=7;}

}

我会做一个这样的对象

yourclass ob1(5);

你能解释一下如何工作吗?如何调用构造函数?

谢谢

4

2 回答 2

1

当你像这样声明一个类的对象时myclass

myclass ob1(5);

这意味着您已经使用第二个接受int参数的构造函数创建了它。换句话说,您从字面上调用了第二个构造函数。顺便说一下,对象是在堆栈上创建的。

当你像这样声明一个类的对象时myclass

myclass ob1;

这意味着您已经使用第一个无参数的构造函数创建了。无参数构造函数的正确术语是默认构造函数。换句话说,您从字面上调用了默认一个)构造函数。顺便说一句,对象也是在堆栈上创建的(如前一种情况)。

当对象在堆栈上创建时,它们会在对象超出范围时自动销毁。范围的概念适用于包括函数/方法/块的代码块您可以通过一对大括号轻松区分块{}。例如:

void function() {
  myclass ob1;
} // <--- think of ob1 being destructed at this point

当函数完成执行时,对象ob1将超出范围,因此ob1自动调用析构函数 for 。另一个例子:

void function() {
  while(true) {
    myclass ob1;
  } // <--- think of ob1 being destructed at this point

  // ob1 does not exist here!
}

注意无限循环和ob1每次迭代在其中创建的对象。您可以清楚地看到花括号定义了一个块,该块可以组合构成每次迭代的多个语句(当前只有 1 个语句)。因此,对象ob1将在每次迭代结束时自动销毁。

范围的概念也适用于类成员。例如,假设您有一个 class ,并且您通过以下方式wrapper声明myclass为它的成员 ( ):m1

class wrapper {
  public:
  myclass m1;
};

然后让我们以前面的示例之一并创建一个wrapper栈上的对象:

void function() {
  wrapper w;
} // <--- destructor of w called first, destructor of w.m1 is called after

首先w开始执行默认构造函数,在此期间w.m1创建(在这种情况下使用默认构造函数,因为我没有在构造函数中指定要调用w哪个构造函数)。w.m1然后构造函数w执行完毕,w就可以认为是正式创建了。的执行function继续。

function完成执行时,w超出范围,并且你还记得它的析构函数会被自动调用。一旦析构函数w完成执行,w.m1也会自动调用析构函数。你可以把它想象成一个对象w在它活着的时候有它自己的内部作用域,一旦它死掉,它的所有成员都会超出作用域并且也应该死掉。

于 2013-04-13T14:02:09.760 回答
0

好的,我们放轻松,一步一步分析。

头等舱

class myclass {
public :
    int a;
    myclass(){a=0; cout<<"first"<<endl;}
    myclass(int i){a=i;cout<<"second"<<endl;}
    ~myclass(){cout<<a<<endl;}
};

这里我们定义了一个类myclass,它有一个atype的成员变量int。它声明了一个默认构造函数(没有参数),它分配给a0然后继续 print first

我们还有一个单参数构造函数,它初始化a到第一个参数并打印second,以及一个析构函数,它在释放之前简单地打印成员变量 a 的值。

初始化列表

现在,在构造函数中,您可以定义表单上的初始化列表

<class name>(...) a(x), b(y), c(z), ... {}
//                ^^^^^^^^^^^^^^^^^^^^^

当类的任何成员变量的类型没有可用的默认构造函数时,此初始化列表是必需的。假设我们创建一个nogood没有默认构造函数的类,并定义我们的主类有一个 type 的成员,nogood他将如何初始化该成员变量?您可以期望它等到构造函数主体被执行。

二等舱

class yourclass : protected myclass {
    int x; 
    myclass m1;
public:
    myclass m2;
    yourclass (int i): m2(3),myclass(i){x=i; a=7;}
};

现在你的类继承protectedmyclass. 这是什么意思?这意味着无论 inmyclass是公共的还是受保护的,都将受到保护yourclass(无论是私有的还是私有的)。

该类yourclass定义了两个私有成员xm1一个公共成员m2。它没有为它定义任何默认构造函数,而是定义了一个参数构造函数(如果需要,它实际上也可以用于隐式转换为intyourclass

输出:构造函数

首先,它调用受保护的子对象的构造函数来生成second. 然后,由于我们没有m1显式初始化,它将使用默认构造函数对其进行初始化,生成输出first。最后在构造函数中,我们初始化m2(3)哪个类型myclass将调用myclass::myclass(int)生产second作为输出。所以输出是:

second
first
second

输出:析构函数

现在对于析构函数调用,它将以与初始化相反的顺序为每个成员变量调用析构函数。初始化的顺序是:m1, m2. 逆序为m2, m1m23初始化列表中m1被初始化0,默认情况下被初始化为。然后最后它调用ob1初始化为的析构函数7。因此最终输出为:

second
first
second
3
0
7
于 2013-04-13T13:58:08.213 回答