40

我对构造函数链接的理解是,当一个类中有多个构造函数(重载构造函数)时,如果其中一个尝试调用另一个构造函数,则此过程称为 CONSTRUCTOR CHAINING ,C++ 不支持。最近我在看网上资料的时候偶然发现了这一段……它是这样的……

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

调用构造函数的成员函数是否也属于构造函数链接?请在 C++ 中对这个主题有所了解。

4

5 回答 5

35

C++11 允许构造函数链接(部分)。此功能称为“委托构造函数”。因此,在 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:对委托构造函数的调用应是唯一的成员初始化程序”。

于 2015-10-22T07:10:30.983 回答
22

该段基本上是这样说的:

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
}
于 2011-09-08T14:01:46.463 回答
3

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

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

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

void Foo::Init() {
  // ... do stuff ...
}
于 2011-09-08T13:58:56.713 回答
0

我不确定它(从成员函数调用构造函数)是否有效,但这是一种不好的做法。将初始化代码移动到新函数是逻辑方式。

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

于 2011-09-08T14:00:37.027 回答
-2

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

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

于 2013-11-16T01:34:57.847 回答