作为一个c#开发人员,我习惯了遍历构造函数:

class Test {
    public Test() {
        DoSomething();
    }

    public Test(int count) : this() {
        DoSomethingWithCount(count);
    }

    public Test(int count, string name) : this(count) {
        DoSomethingWithName(name);
    }
}

在c++中有办法做到这一点吗?

我尝试调用类名和使用'this'关键字,但都失败了。


当前回答

不,在c++中,你不能从构造函数调用构造函数。正如沃伦指出的,你能做的是:

使用不同的签名重载构造函数 在参数上使用默认值,使“更简单”的版本可用

请注意,在第一种情况下,不能通过从一个构造函数调用另一个构造函数来减少代码重复。当然,你可以有一个单独的私有/受保护的方法来完成所有的初始化,让构造函数主要处理参数处理。

其他回答

简单地说,你不能在c++ 11之前。

c++ 11引入了委托构造函数:

Delegating constructor If the name of the class itself appears as class-or-identifier in the member initializer list, then the list must consist of that one member initializer only; such constructor is known as the delegating constructor, and the constructor selected by the only member of the initializer list is the target constructor In this case, the target constructor is selected by overload resolution and executed first, then the control returns to the delegating constructor and its body is executed. Delegating constructors cannot be recursive. class Foo { public: Foo(char x, int y) {} Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int) };

请注意,委托构造函数是一个全有或全无的提议;如果一个构造函数委托给另一个构造函数,则调用构造函数的初始化列表中不允许有任何其他成员。如果只初始化一次const/reference成员,这是有意义的。

在c++ 11中,一个构造函数可以调用另一个构造函数重载:

class Foo  {
     int d;         
public:
    Foo  (int i) : d(i) {}
    Foo  () : Foo(42) {} //New to C++11
};

此外,成员也可以这样初始化。

class Foo  {
     int d = 5;         
public:
    Foo  (int i) : d(i) {}
};

这样就不需要创建初始化帮助器方法了。并且仍然建议不要在构造函数或析构函数中调用任何虚函数,以避免使用任何可能未初始化的成员。

这种方法可能适用于某些类型的类(当赋值操作符表现“良好”时):

Foo::Foo()
{
    // do what every Foo is needing
    ...
}

Foo::Foo(char x)
{
    *this = Foo();

    // do the special things for a Foo with char
    ...
}

如果你想变邪恶,你可以使用“new”操作符:

class Foo() {
    Foo() { /* default constructor deliciousness */ }
    Foo(Bar myParam) {
      new (this) Foo();
      /* bar your param all night long */
    } 
};

似乎对我有用。

edit

正如@ElvedinHamzagic指出的,如果Foo包含一个分配内存的对象,那么该对象可能不会被释放。这使事情更加复杂。

一个更普遍的例子:

class Foo() {
private:
  std::vector<int> Stuff;
public:
    Foo()
      : Stuff(42)
    {
      /* default constructor deliciousness */
    }

    Foo(Bar myParam)
    {
      this->~Foo();
      new (this) Foo();
      /* bar your param all night long */
    } 
};

看起来确实没那么优雅。@JohnIdol的解决方案好多了。

我建议使用private friend方法,该方法实现了构造函数的应用逻辑,并由各种构造函数调用。这里有一个例子:

假设我们有一个名为StreamArrayReader的类,它带有一些私有字段:

private:
    istream * in;
      // More private fields

我们想定义两个构造函数:

public:
    StreamArrayReader(istream * in_stream);
    StreamArrayReader(char * filepath);
    // More constructors...

其中第二个简单地使用了第一个(当然,我们不想复制前者的实现)。理想情况下,人们会做如下事情:

StreamArrayReader::StreamArrayReader(istream * in_stream){
    // Implementation
}

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    StreamArrayReader(&instream);
    instream.close();
}

然而,这在c++中是不允许的。因此,我们可以定义一个私有友方法,如下所示,它实现了第一个构造函数应该做的事情:

private:
  friend void init_stream_array_reader(StreamArrayReader *o, istream * is);

现在这个方法(因为它是一个朋友)可以访问o的私有字段。然后,第一个构造函数变成:

StreamArrayReader::StreamArrayReader(istream * is) {
    init_stream_array_reader(this, is);
}

注意,这不会为新创建的副本创建多个副本。第二个是:

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    init_stream_array_reader(this, &instream);
    instream.close();
}

也就是说,不是一个构造函数调用另一个构造函数,而是两个构造函数都调用一个私有友元!