在C++中,我可以从另一个构造函数中调用构造函数(进行构造函数链)吗?

1138
作为一名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'关键字,但都失败了。

1
在所提到的上下文中使用thisauto将是未来重构目的的有趣关键字。 - sergiol
15个回答

3

这种方法对某些类型的类可能有效(当赋值运算符表现良好时):

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

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

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

2
我建议使用一个 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();
}

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

在我看来,使用友元方法与普通的私有方法相比没有任何优势。你为什么要这样做呢? - pqnet

0

当调用构造函数时,它实际上会分配内存,可以从堆栈或堆中分配。因此,在另一个构造函数中调用构造函数会创建一个本地副本。因此,我们修改的是另一个对象,而不是我们关注的对象。


1
你不能“调用构造函数”;请查看我对ohlemacher答案的评论。然而,从本质上讲,你是正确的。 - Lightness Races in Orbit
构造函数只是一个初始化器,因此在构造函数之外创建通用的初始化器是一种过时的方法。内存在构造函数被调用之前就已经分配好了,通常是在调用operator new或malloc时进行... - Elvedin Hamzagic

0

如果我正确理解你的问题,你是在问是否可以在 C++ 中调用多个构造函数?

如果这就是你想要的,那么不行 - 这是不可能的。

你当然可以有多个构造函数,每个都有独特的参数签名,然后在实例化新对象时调用你想要的那个。

你甚至可以有一个带有默认参数的构造函数。

但你不能拥有多个构造函数,然后单独调用它们。


4
他在询问一个构造函数是否可以调用另一个构造函数。Java和C#允许这样做。 - Jonathan

-1

测试比决定更容易 :) 试试这个:

#include <iostream>

class A {
public:
    A( int a) : m_a(a) {
        std::cout << "A::Ctor" << std::endl;    
    }
    ~A() {
        std::cout << "A::dtor" << std::endl;    
    }
public:
    int m_a;
};

class B : public A {
public:
    B( int a, int b) : m_b(b), A(a) {}
public:
    int m_b;
};

int main() {
    B b(9, 6);
    std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl;    
    return 0;
}

并使用98标准进行编译: g++ main.cpp -std=c++98 -o test_1

您将看到:

A::Ctor
Test constructor delegation a = 9; b = 6
A::dtor

所以 :)


2
这不是最初的问题,他并不是在询问如何调用基类构造函数,而是在询问如何调用同一类中的另一个构造函数。 - M. Yousfi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接