c++构造函数调用构造函数




我可以使用C++从另一个构造函数(构造函数链)调用构造函数吗? (10)

作为一名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 ++ 11:是的!

C ++ 11及以后版本具有相同的功能(称为委托构造函数 )。

语法与C#稍有不同:

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {}
};

C ++ 03:没有

不幸的是,在C ++ 03中没有办法做到这一点,但有两种模拟方式:

  1. 您可以通过默认参数组合两个(或更多)构造函数:

    class Foo {
    public:
      Foo(char x, int y=0);  // combines two constructors (char) and (char, int)
      // ...
    };
    
  2. 使用init方法共享通用代码:

    class Foo {
    public:
      Foo(char x);
      Foo(char x, int y);
      // ...
    private:
      void init(char x, int y);
    };
    
    Foo::Foo(char x)
    {
      init(x, int(x) + 7);
      // ...
    }
    
    Foo::Foo(char x, int y)
    {
      init(x, y);
      // ...
    }
    
    void Foo::init(char x, int y)
    {
      // ...
    }
    

请参阅C ++ FAQ条目以供参考。


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

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

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


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

#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 std:g ++ main.cpp -std = c ++ 98 -o test_1进行编译

你会看见:

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

所以:)


值得指出的是,您可以在构造函数中调用父类的构造函数,例如:

class A { /* ... */ };

class B : public A
{
    B() : A()
    {
        // ...
    }
};

但是,不,你不能调用同一个类的另一个构造函数。


C++11Wikipedia

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) {}
};

这应该消除创建初始化帮助程序方法的需要。 仍然建议不要在构造函数或析构函数中调用任何虚函数,以避免使用可能未初始化的任何成员。


在Visual C ++中,你也可以在构造函数中使用这个符号:this-> Classname :: Classname(另一个构造函数的参数)。 看到下面的例子:

class Vertex
{
 private:
  int x, y;
 public:
  Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
  Vertex()
  {
   this->Vertex::Vertex(-1, -1);
  }
};

我不知道它是否可以在其他地方使用,我只在Visual C ++ 2003和2008中测试过。您可能也会这样调用几个构造函数,我想,就像在Java和C#中一样。

PS:坦率地说,我很惊讶,这是没有提到过。


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

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

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

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

但是你可能没有多个构造函数,然后分别调用它们中的每一个。


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


我相信你可以从构造函数中调用构造函数。 它会编译并运行。 我最近看到有人这样做,它在Windows和Linux上运行。

它只是不做你想要的。 内部构造函数将构造一个临时局部对象,一旦外部构造函数返回就会被删除。 它们必须是不同的构造函数,否则您将创建递归调用。

参考: https//isocpp.org/wiki/faq/ctors#init-methods


简而言之,你不能在C ++ 11之前。

C ++ 11引入了委托构造函数

委托构造函数

如果类的名称本身在成员初始值设定项列表中显示为类或标识符,则该列表必须仅包含该成员初始值设定项; 这样的构造函数被称为委托构造函数,并且由初始化方列表的唯一成员选择的构造函数是目标构造函数

在这种情况下,目标构造函数是通过重载解析来选择并首先执行的,然后控件返回到委托构造函数并执行其主体。

委托构造函数不能递归。

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};

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







constructor