构造函数可以在 c++ 中调用另一个构造函数吗?

Can constructor call another constructor in c++?

提问人:MainID 提问时间:12/13/2009 最后编辑:Michael Krelin - hackerMainID 更新时间:11/10/2018 访问量:44553

问:

class A{
  A(int a = 5){
    DoSomething();
    A();
  }
  A(){...}
}

第一个构造函数可以调用第二个构造函数吗?

C++ 构造函数

评论

1赞 Jon Cage 1/9/2015
类似的问题在这里:http://stackoverflow.com/questions/308276/......

答:

69赞 Pavel Radzivilovsky 12/13/2009 #1

不是在 C++11 之前

改为将通用功能提取到单独的函数中。我通常将这个函数命名为 construct()。

“所谓的”第二次调用将编译,但在 C++ 中具有不同的含义:它将构造一个新对象,一个临时对象,然后在语句末尾立即删除。所以,不。

但是,可以毫无问题地调用析构函数。

评论

5赞 Klaim 12/14/2009
+1 - 您应该补充一点,在下一个 C++ 版本 (C++0x) 中可以从同一类中的构造函数调用构造函数。查看 www2.research.att.com/~bs/C++0xFAQ.html#delegating-ctor
0赞 MattCochrane 4/9/2017
你能举一个construct()函数的例子吗?我知道这很简单,但我认为人们会发现它很有用。
0赞 peterk 11/10/2017
是的,真正的问题是初始化引用,就好像你有一堆一样,你必须在每个构造函数重载中复制所有初始化,并且不能将它们分解为一个通用的构造函数子例程。并且它们只能在 pre-{ 初始值设定项中初始化。
19赞 Alex B 12/13/2009 #2

不是在 C++0x 之前,没有。

但是,只是出于学术兴趣,我想出了一种非常可怕的方法*来使用放置运算符“新”来做到这一点(有人愿意指出这是多么便携?

#include <new>
#include <iostream>

class A
{
public:
    A(int i, int j)
        : i_(i), j_(j) { }

    A(int i)
    { new (this) A(i, 13); }

    int i_,j_;
};

int
main() {
    A a1(10,11), a2(10);
    std::cout
        << a1.i_ << ", "
        << a1.j_ << std::endl
        << a2.i_ << ", "
        << a2.j_ << std::endl;
    return 0;
}

*地狱不,我没有在生产代码中写这个。

评论

1赞 emvee 6/24/2010
我认为它非常便携;placement-new 在 ISO C++ 标准中。“然而,其他用途包括直接调用构造函数,这是C++语言不允许的。来自维基百科: en.wikipedia.org/wiki/Placement_syntax
4赞 paercebal 10/16/2010
如果 A 派生自 B 类会发生什么?将调用 B 的构造函数,然后调用 A,然后调用新的 A'(另一个 A 构造函数),并覆盖 B 已经完成的所有操作,然后再次调用 B,然后调用 A'。结论:如果 B 做了一些有意义的事情(即分配资源),这将破坏代码(即引发资源泄漏)。
0赞 Alex B 10/16/2010
@paercebal是的,如果 A 是抽象类,这也行不通。
6赞 anon 12/13/2009 #3

答案实际上是“是”,但正如其他人所建议的那样,它并没有做你想做的事。当然,您可以隐式或显式地使用基类的构造函数:

struct B {
    B() {}
    B( int x ) {}
};

struct A : public B {
    A() {}    // calls B() implicitly
    A( int a, int b ) : B( b ) {} // calls B(int) explicitly
};
3赞 jalf 12/13/2009 #4

不是直接的。有几种方法可以解决这个问题。

从类构造函数的初始值设定项列表中,可以在任何基类和所有成员变量上调用构造函数。

因此,您通常可以重构您的类并将其拆分为几个较小的类来解决问题。通常执行的代码可以放在成员对象或基类中。然后,每个主类的构造函数只需要决定使用哪个构造函数来初始化该成员。

class B {
  B() {  }
  B(int b) { DoSomething(); }
}
class A{
  A(int a = 5) : b(a) { } // call B's constructor which does something
  A() : b() {} // call B's constructor which does nothing

  B b;
};
3赞 supaflav 9/19/2013 #5

这是一个老问题;然而

class A{
  A(int a = 5){
    DoSomething();
    A();
  }
  A(){...}
}

可能是

class A{
  A(int a = 5){
    *this = A();
    DoSomething();
  }
  A(){...}
}

评论

1赞 austinmarton 4/21/2016
我认为它将使用默认的复制构造函数(如果您尚未定义一个),这可能不是您想要的?*this = A();
3赞 Pierre Wargnier 11/10/2018 #6

正如Pavel Radzivilovsky在他的回答中指出的那样,从C++ 11开始,这是可能的。它与从子类显式调用父类的类构造函数的语法相同。当一个类需要有多个构造函数(例如,一个默认构造函数和一个具有属性初始化的构造函数)时,这很有用,但某些操作必须在所有情况下完成。这样可以避免代码重复。

下面是一个示例:

class A
{
public:

    A()
    {
         foo();
    }

    A(Attribute attribute) : A()
    {
         this->attribute = attribute;
    }

    //------ some other code --------

private:

    Attribute attribute;
    void foo()
    {...}

    //------ some other code -------
};

在这个简单的示例中,我假设在所有情况下都需要调用函数 foo() 才能正确初始化对象。使用此语法时,如果调用第二个构造函数(具有属性初始化功能),它将首先在默认构造函数中执行操作,然后再执行属性初始化构造函数中的指令。

也可以反过来完成:默认构造函数可以调用另一个具有默认参数的构造函数。

在 C++ 11 之前,必须复制所有构造函数的通用指令或定义执行实际对象初始化的方法。