2011-09-08 162 views
26

我对构造函数链的理解是,当一个类中有多个构造函数(重载构造函数)时,如果其中一个构造函数试图调用另一个构造函数,那么这个过程称为CON​​STRUCTOR CHAINING,它在C++中不受支持。 最近我碰到这一段就在阅读在线素材....它是这样的......C++构造函数链

你可能会发现自己在你想写一个成员函数的情况重新初始化类回默认值。因为你可能已经有了这样的构造函数,所以你可能会试图从你的成员函数中调用构造函数。如前所述,链接构造函数调用在C++中是非法的。你可以从你的函数中的构造函数复制代码,这将工作,但会导致重复的代码。在这种情况下,最好的解决方案是将代码从构造函数移动到新函数,并让构造函数调用您的函数来完成初始化数据的工作。

调用构造函数的成员函数是否也在构造函数链中? 请在C++中关注这个主题。

+3

我说不是,这是一个非不合逻辑的文章说,构造函数链是非法的,他说,一些任意的成员函数(不一定是一个构造函数)可能会认为它要调用构造函数来重置后立即价值。但是谁知道,你还没有引用这篇文章或引用它描述构造函数链的地方,所以也许它在别处已经描述过的一些不寻常的意义上使用它。 –

+1

这不是非法的。从成员调用构造函数的效果是创建一个适用于该构造的临时对象,而不是创建该调用的“this”对象。 –

+1

@Amardeep:同意,这将是更准确的说,构造函数链是C++ 03“不可能的”,而不是“非法”。没有语法来描述这样做。正如你所说,通过调用构造函数的正常定义与构造函数链并不完全相同。 –

回答

17

段落基本上这样说:

class X 
{ 
    void Init(params) {/*common initing code here*/ } 
    X(params1) { Init(someParams); /*custom code*/ } 
    X(params2) { Init(someOtherParams); /*custom code*/ } 
}; 

不能调用从一个成员函数构造无论是。它可能在你看来,你已经做了,但是这是一个错觉:

class X 
{ 
public: 
    X(int i):i(i){} 
    void f() 
    { 
     X(3); //this just creates a temprorary - doesn't call the ctor on this instance 
    } 
    int i; 
}; 

int main() 
{ 
    using std::cout; 
    X x(4); 
    cout << x.i << "\n"; //prints 4 
    x.f(); 
    cout << x.i << "\n"; //prints 4 again 
} 
+0

@阿门。你的意思是它第一次被打印4,它实际上是调用构造函数,而第二遍的时候它打印4,虽然我觉得我已经通过调用构造函数(由函数void来达到的结果f()),究竟发生了什么并不是那样.. !!!是吗 ??但我不明白你在上面的代码中的第一个注释//这只是创建一个临时的 - 不在这个实例上调用ctor。你能否更清楚地向我解释一下? – jsp99

+0

这已经改变了与C + + 11,请参阅http://stackoverflow.com/a/33275207/1915854 –

3

这不是文字所说的。它建议你的构造函数调用一个正常和合法的成员函数。这是为了避免再次明确地调用ctor并避免在ctor和reset函数之间重复代码。

Foo::Foo() { 
    Init(); 
} 

void Foo::Reset() { 
    Init(); 
} 

void Foo::Init() { 
    // ... do stuff ... 
} 
+0

这是真的,文字不建议该功能调用构造函数,但是文本显示“你可能试图从你的成员函数中调用构造函数,如前所述,链接构造函数调用在C++中是非法的”。这表明,通过一些想法的混淆,作者认为“链接构造函数调用”与“从成员函数调用构造函数”有关,无论该文章是否推荐使用该构造函数。当然,可能只是编辑不当。 –

+0

“因为你可能已经有了这样的构造函数,所以你可能会试图从你的成员函数中调用构造函数。”我认为这意味着应该避免召集建设者的成员函数.. !! – jsp99

+0

@Appy:不一定。例如,在一个名为'Foo'' * this = Foo();的类中'可能是一个完全合理的重置对象的方法,如果不是最有效的。然后该函数调用构造函数,它不会调用它来构造'this'。 –

0

我不知道,如果它(从调用一个成员函数构造函数)将工作或没有,但它是一个不好的做法。将初始化代码移动到新函数是逻辑方式。

基本上是说,不要调用构造函数,除非你构建...

+0

这不只是坏习惯......它不能正常工作。 – Johnsyweb

+0

我同意Johnsyweb。从另一个构造函数调用构造函数只会在其中创建一个临时局部变量,并在构造函数退出后将其删除。这个对象不受任何影响。要做到这一点的唯一方法就是重新放置一个贴图,并重复C++ FAQ,这是一件可怕的事情。 – MasterMastic

1

当我们调用从一个成员函数的构造函数,那么它会临时创建的类型的对象。 如果我们在派生类函数中调用,那么一旦函数超出作用域,所有父构造函数也会被析构函数执行和销毁。

由于它创建派生的每个类的对象,因此在成员函数中调用构造函数并不是一个好习惯。

15

C++ 11允许构造函数链接(部分)。该功能称为“delegating constructors”。因此,在C++ 11,你可以做以下

class Foo 
{ 
public: 
    Foo(int a) : Foo() { _a = a; } 
    Foo(char* b) : Foo() { _b = b; } 
    Foo() { _c = 1.5; } 
private: 
    int _a = 0; 
    char* _b = nullptr; 
    double _c; 
}; 

然而,有一个调用另一个构造函数构造不允许初始化任何其他成员的一个严重的限制。所以你不能做一个委托构造函数如下:

class Foo 
{ 
public: 
    Foo(int a) : Foo(), _a(a) { } 
    Foo(char* b) : Foo(), _b(b) { } 
    Foo() { _c = 1.5; } 
private: 
    int _a = 0; 
    char* _b = nullptr; 
    double _c; 
}; 

MSVC++ 2013提供了编译错误“C3511:到委托构造函数的调用应是唯一的成员初始化”后者的代码示例。