简体   繁体   English

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

[英]Can constructor call another constructor in c++?

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

Can the first constructor call the second one? 第一个构造函数可以调用第二个构造函数吗?

Not before C++11 . 不是在C ++ 11之前

Extract the common functionality into a separate function instead. 将常用功能提取到单独的功能中。 I usually name this function construct() . 我通常将此函数命名为construct()

The "so-called" second call would compile, but has a different meaning in C++: it would construct a new object, a temporary, which will then be instantly deleted at the end of the statement. “所谓的”第二次调用将编译,但在C ++中具有不同的含义:它将构造一个新对象,一个临时对象,然后在语句结束时立即删除。 So, no. 所以不行。

A destructor, however, can be called without a problem. 但是,可以毫无问题地调用析构函数。

Not before C++0x , no. 不是在C++0x之前,没有。

BUT, just out of academic interest I've come up with a really horrible way* to do it using a placement operator "new" (someone care to point out how portable this is?) 但是, 出于学术兴趣,我想出了一个非常可怕的方法*使用贴片操作员“new”来做这件事(有人想指出这是多么便携?)

#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;
}

*Hell no, I don't write this in the production code. *不,不,我不在生产代码中写这个。

The answer is in fact "yes", but as others have suggested, it doesn't do what you want. 答案实际上是“是”,但正如其他人所建议的那样,它并不能满足您的需求。 You can of course use the constructor of a base class, either implicitly or explicitly: 您当然可以隐式或显式地使用基类的构造函数:

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

Not directly. 不是直接的。 There are a few ways to work around this. 有几种方法可以解决这个问题。

From the initializer list of your class' constructor, you can call a constructor on any base class, and on all member variables. 从类的构造函数的初始化列表中,您可以在任何基类和所有成员变量上调用构造函数。

So you can usually refactor your class and split it into several smaller ones to solve the problem. 因此,您通常可以重构您的类并将其拆分为几个较小的类来解决问题。 The commonly executed code can be placed in a member object or perhaps a base class. 通常执行的代码可以放在成员对象中,也可以放在基类中。 Then each of the main class' constructors just have to decide which construcotr to use to initialize that member. 然后每个主类的构造函数只需要决定使用哪个构造函数来初始化该成员。

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

As pointed out by Pavel Radzivilovsky in his answer, since C++ 11 , it is possible. 正如Pavel Radzivilovsky在他的回答中指出的那样,自C ++ 11以来,它是可能的。 It is the same syntax as for explicitely calling the parent's class constructor from a child class. 它与从子类中明确调用父类的构造函数的语法相同。 This is useful when a class needs to have multiple constructors (say, a default constructor and a constructor with attribute initialization) but some operations have to be done in all cases. 当一个类需要有多个构造函数(比如一个默认构造函数和一个带属性初始化的构造函数)时,这很有用,但是在所有情况下都必须完成一些操作。 This allows to avoid code repetitions. 这允许避免代码重复。

Here is an example: 这是一个例子:

class A
{
public:

    A()
    {
         foo();
    }

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

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

private:

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

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

In this simple example, I assume that the function foo() needs to be called in all cases for the object to be correctly initialized. 在这个简单的例子中,我假设在所有情况下都需要调用函数foo()才能正确初始化对象。 With this syntax, if the second constructor (with attribute initialization) is called, it will first perform the operations in the default constructor before executing the instructions in the attribute-initialization constructor. 使用此语法,如果调用第二个构造函数(具有属性初始化),它将在执行属性初始化构造函数中的指令之前首先在默认构造函数中执行操作。

It can also be done the other way around: the default constructor can call another constructor with default parameters. 它也可以通过其他方式完成:默认构造函数可以使用默认参数调用另一个构造函数。

Before C++ 11, it was necessary to duplicate the common instructions of all constructors or define methods that do the actual object initialization. 在C ++ 11之前,有必要复制所有构造函数的公共指令或定义执行实际对象初始化的方法。

This is an old question; 这是一个老问题; however, 然而,

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

could be 可能

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM