以对象为参数的构造函数

Constructors with objects as parameters

假设我有一个class如下:

class A{
    int x ; 
    A( int i ){
        x = i ; 
    }
}

我还有另一个 class B,它有一个 class A 的实例作为成员对象。

class B{
    int y ; 
    A obj_a ; 
    B( int j , A a ){
        y = j ; 
        obj_a = a ; 
    }
}

当我执行以下操作时:

int main(){
        A obj1( 1 ) ; // obj.x has value 1
        B obj2( 2 , obj1 ) ; 
    }

第 2 行抛出一个错误,指出没有 A::A() 形式的函数调用。我知道这意味着缺少默认样式构造函数,但我为什么需要它? obj1 是使用定义的构造函数创建的,因此这不是问题。

我目前的想法是 A aobj_a = a 将调用隐式定义的复制构造函数。

注意:为简洁起见,我已经排除了 private、public 等。

obj_a = a 调用 operator=,而不是复制构造函数。问题是,obj_a 是使用默认构造函数初始化的,因为您没有在初始化列表中指定要调用哪个构造函数。

B( int j , A a ) /*: obj_a{}*/ { /*...*/ }
                 ^^^^^^^^^^^^^
          implicit call to default constructor

您必须使用成员初始化列表中的一个参数显式调用构造函数:

B( int j , A a ) : obj_a{ a } { /*...*/ }

一个对象必须是完全一致的,在它进入构造函数的主体时,它的所有成员都已构造。所以在

B( int j , A a ){
    y = j ; 
    obj_a = a ; 
}

之前

{
    y = j ; 
    obj_a = a ; 
}

有机会做任何事情,obj_a一定是建造好了。

由于 Member Initializer List 没有提供关于如何构建 obj_a 的说明,因此 obj_a 将使用 class [=16= 的默认构造函数构建]. Class A没有默认构造函数,没有A::A(),所以报错

解决方案是使用成员初始化器列表而不是在函数体内赋值。这不仅可以节省您构建一个将立即被覆盖的对象的时间,而且编译器还有更多的优化余地,您可能会得到一些其他的小改进。

Class B 应该是:

class B{
    int y ; 
    A obj_a ; 
    B( int j , A a ): y(j), obj_a(a)
    {
    }
}