构造函数调用顺序与组合 [英] constructor calling order with composition

查看:187
本文介绍了构造函数调用顺序与组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有A类和B类。类C从B类派生并且具有作为组成的A类对象。 http://ideone.com/JGT48M

  #includeiostream
using namespace std;

class A {
int i;
public:
A(int ii):i(ii){
cout< \\\
A的构造函数称为\\\
;

}
〜A(){
cout< \\\
析构函数的A称为\\\
;
}
void f()const {}
};

class B {
int i;
public:
B(int ii):i(ii){
cout< \\\
B的构造函数称为\\\
;
}
〜B(){
cout<< \\\
析构函数的B称为\\\
;
}
void f()const {}
};

class C:public B {
A a;
public:
C(int ii):a(ii),B(ii){
cout< \\\
C的构造函数称为\\\
;
}
〜C(){
cout<< \\\
析构函数的C称为\\\
;
} //调用〜A()和〜B()
void f()const {//重定义
a.f();
B :: f();
}
};

int main(){
C c(47);
} ///:〜



我读了构造函数被调用,在我的派生类构造函数中调用。我的意思是,让一个类REF从REF_BASE1和REF_BASE2派生然后

  REF(int ii):REF_BASE2 ii),REF_BASE1(ii){

将意味着REF_BASE2将首先调用,然后调用REF_BASE1,然后调用REF构造函数被调用。
,如果我们定义它像

  REF(int ii):REF_BASE1(ii),REF_BASE2(ii){ 

意味着REF_BASE1将首先调用,然后调用REF_BASE2,然后调用REF构造函数。



然而,在我的程序中,我明确地错误地声明,通过内部组合变量A首先被初始化,然后B应该被初始化,但编译器以正确的方式,但失败让我知道我的错误



输出上面的程序不管顺序我指定在派生类constcutor初始化列表

  B的构造函数称为

A的构造函数称为

C的构造函数称为

的析构函数称为

B的析构函数叫做

的析构函数叫做

我的问题是
1)为什么编译器不报错?或者我是正确的?
2)是派生构造函数中的顺序不严格遵循?

解决方案

我将从第二个问题开始:


2)是派生构造函数中的顺序是否严格遵循?


顺序不是出现在



所以如果你的类定义看起来像这样:

  struct A:B,C 
{
// ...
}

然后将调用 B 的构造函数无论你在 A 的构造函数的初始化列表中指定什么顺序, C 的构造函数之前。 p>

C ++ 11标准的第12.6.2 / 10段规定:


在非委托构造函数中,初始化按以下顺序进行:



- 首先,只有最衍生类(1.8)的构造函数,虚拟基类在
中初始化它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序,
其中从左到右是基础的出现顺序



- 直接基类按声明顺序初始化,因为它们出现在base-specifier-list
(不考虑mem初始化器的顺序)



- 然后,非静态数据成员按照它们的顺序初始化在类定义
中声明(再次不考虑mem初始化器的顺序)。



- 最后,执行构造函数体的复合语句。


现在的第一个问题:


1)为什么编译器不提出申诉?


编译器构造函数初始化列表不同于基类列表中的(GCC使用 -Wall ),但不是必须的。最终,只有后者很重要。


I have a class A and Class B . Class C derives from Class B and has Class A object as composition . http://ideone.com/JGT48M

#include "iostream"
using namespace std;

class A {
  int i;
public:
  A(int ii) : i(ii) {
      cout << "\n Constructor of A is called \n";

  }
  ~A() {
      cout << "\n destructor  of A is called \n";
  }
  void f() const {}
};

class B {
  int i;
public:
  B(int ii) : i(ii) {
      cout << "\n Constructor of B is called \n";
  }
  ~B() {
      cout << "\n destructor  of B is called \n";
  }
  void f() const {}
};

class C : public B {
  A a;
public:
  C(int ii) : a(ii), B(ii) {
      cout << "\n Constructor of C is called \n";
  }
  ~C() {
  cout << "\n destructor  of C is called \n";
  } // Calls ~A() and ~B()
  void f() const {  // Redefinition
    a.f();
    B::f();
  }
};

int main() {
  C c(47);
} ///:~

I have read that constructors are called based on how they are called in my derived class constructor . What i mean is that let there be a class called REF derived from REF_BASE1 and REF_BASE2 then

 REF (int ii) : REF_BASE2(ii), REF_BASE1 (ii) {

would mean that REF_BASE2 would be called first then REF_BASE1 and then REF constructor is called . and if we defined it like

REF (int ii) : REF_BASE1(ii), REF_BASE2 (ii) {

would mean that REF_BASE1 would be called first then REF_BASE2 and then REF constructor is called .

However in my program above i have explicitly "wrongly" stated that by internal composition variable A a be initialized first and then B should get initialized , yet the compiler does it the right way but fails to let me know of my mistake

output of above program irrespective of order i specify in derived class constcutor initialization list is

Constructor of B is called 

 Constructor of A is called 

 Constructor of C is called 

 destructor  of C is called 

 destructor  of A is called 

 destructor  of B is called 

My question is 1) why does compiler not complain ? or am i correct ? 2) is the order in derived constructor not followed strictly ?

解决方案

I will start with the second question:

2) is the order in derived constructor not followed strictly ?

The order is not the one that appears in your constructor's initialization list, but rather the one in which the base classes appear in your class definition.

So if your class definition looks like this:

struct A : B, C
{
    // ...
};

Then the constructor of B will be called before the constructor of C, no matter what order you specify in the initialization list of A's constructor.

Paragraph 12.6.2/10 of the C++11 Standard specifies:

In a non-delegating constructor, initialization proceeds in the following order:

— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where "left-to-right" is the order of appearance of the base classes in the derived class base-specifier-list.

— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

— Finally, the compound-statement of the constructor body is executed.

Now the first question:

1) why does compiler not complain ?

The compiler may warn you that the initialization order in the constructor initializer list is different from the one in the base class list (GCC does with -Wall), but does not have to. Eventually, only the latter matters.

这篇关于构造函数调用顺序与组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆