【问题标题】:Constructors with objects as parameters以对象为参数的构造函数
【发布时间】:2017-03-01 12:10:58
【问题描述】:

假设我有一个类如下:

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

我还有另一个类 B,它有一个类 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 ) ; 
    }

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

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

注意:为简洁起见,我排除了私有、公共等。

【问题讨论】:

  • 发布实际错误。您的 ctor 可能在抱怨应该是 const int i;
  • 你明确要求它不使用初始化列表。

标签: c++ class c++11 constructor copy-constructor


【解决方案1】:

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

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

之前

{
    y = j ; 
    obj_a = a ; 
}

有机会做任何事情,obj_a 一定已经被构建了。

由于Member Initializer List 中没有提供有关如何构造obj_a 的说明,因此obj_a 将使用类A 的默认构造函数来构建。类A没有默认构造函数,没有A::A(),所以报错。

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

B 类应该是:

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

【讨论】:

  • 对象a是这里的值创建的吗?是否可以通过引用传递?
  • @AbhinavVishak a 目前是按值传递的,可能需要一个副本。是的,您可以通过引用传递a
【解决方案2】:

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 } { /*...*/ }

【讨论】:

  • 好吧,obj_a = a 的问题并不多。它是参数列表中的A a。我该如何解决?
  • @AbhinavVishak A a 在参数列表中时不是问题。问题是 mem-initialiser 列表(: 之后的列表)中缺少 obj_a
  • @agnew 我做了您建议的更改,并且可以编译。谢谢 !我对初始化列表的使用仍然有些困惑,我会对此进行一些阅读。我假设使用 ` : obj_a{a} ` 后,我不需要obj_a = a ??
猜你喜欢
  • 2013-08-29
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-23
  • 1970-01-01
相关资源
最近更新 更多