从另一个成员函数/构造函数调用C ++构造函数是否执行初始化列表?

时间:2012-05-04 18:59:55

标签: c++ list constructor initializer

在C ++对象中,当你从另一个构造函数或成员函数调用构造函数时(在构造了对象之后),你正在调用的构造函数的初始化列表是否仍然被执行?

4 个答案:

答案 0 :(得分:2)

在C ++ 11中,您可以将构造函数委托给同一个类中的另一个构造函数,例如 1

#include <iostream>
struct SomeType  {
    int number;

    SomeType(int new_number) : number(new_number) {}
    SomeType() : SomeType(42) {}
};

int main() {
  SomeType a;
  std::cout << a.number << std::endl;
}

在这种情况下,禁止在此授权后拥有一份资助者名单,例如:将上一个示例更改为:

SomeType() : SomeType(42), number(0) {}

是一个错误。


如果问题是“给定继承关系,是否还会调用initaliser列表?”答案是肯定的,例如

#include <iostream>
struct SomeBase {
  SomeBase(int) {}
};

struct SomeType : SomeBase {
    int number;

    SomeType(int new_number=0) : SomeBase(new_number), number(new_number) {}
};

int main() {
  SomeType a;
  std::cout << a.number << std::endl;
}

这很好,并且完全符合您的希望。


从C ++ 11之前的另一个构造函数和C ++中直接调用构造函数是不合法的,也不允许构造函数委托,所以像这样:

#include <iostream>

struct SomeType {
    int number;

    SomeType(int new_number) : number(new_number) {}
    SomeType() {
      SomeType::SomeType(0); // Error!
    }
};

int main() {
  SomeType a;
  std::cout << a.number << std::endl;
}

是错误而无法直接表达。

以下(我猜这是您在撰写问题时的想法)示例不是错误,但是没有做您希望的事情:

#include <iostream>

struct SomeType {
    int number;

    SomeType(int new_number) : number(new_number) {}
    SomeType() {
      SomeType(0); 
      number = 42;
    }
};

int main() {
  SomeType a;
  std::cout << a.number << std::endl;
}

这里没有参数的构造函数构造SomeType的匿名临时实例。它是一个完全独立的实例,最初是为构造函数调用的实例。这是完全合法的,但可能不是你想要做的。如果你这样做,那么如果你不小心你可能会产生无限递归,我认为如果你最终做这样的事情,它可能是设计问题的一个很好的指标!

1 来自维基百科C++11 article

答案 1 :(得分:1)

我假设您指的是从派生类的初始化列表中调用WITHIN的基类构造函数。假设是这种情况,则首先执行BASE类构造函数(包括其初始化列表),然后调用派生类的初始化列表。

如果您想知道 - 在为派生类执行初始化程序列表之前始终调用基类构造函数,即使对基类构造函数的调用显式出现在派生类的初始化程序的中间或末尾也是如此列表(以及它是否出现在开头)。原因是初始化程序列表中的项目按它们在类头文件中的类DECLARATION中出现的顺序执行,而不是按照它们出现在构造函数定义的初始化程序列表中的顺序执行。而且, base 类构造函数永远不会在派生类声明中声明。 C ++要求在派生类构造函数之前始终调用基类构造函数 - 对基类构造函数的调用是否显式出现在派生类的初始化列表中 - 无论它出现在初始化列表中的哪个位置。

答案 2 :(得分:0)

不要从另一个方法或其他构造函数中显式调用构造函数。

如果您确实需要in,则使用两阶段初始化,在构造对象后调用Init()类型方法。

答案 3 :(得分:0)

您无法通过new或堆栈上的对象构造显式调用构造函数。有办法破解它(例如放置新的)但不要这样做,只需使用两阶段构造&amp;初始化。