C ++如何使用隐藏的默认构造函数初始化成员?

时间:2017-12-01 18:37:08

标签: c++ constructor initialization c++14 atmelstudio

我有一个带有隐藏默认构造函数的类,强制使用带参数的构造函数。另一个类使用该类的2个实例:

typedef struct { ... } BAZ;

class Foo {
  private:
    Foo(void) {}

  public:
    Foo(BAZ a) { ... }
};

class Bar {
  private:
    Foo foo1;
    Foo foo2;

    Bar(void) {}

  public:
    Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
};

最明显的是变量foo1和foo2的声明将调用默认的Foo构造函数,但由于它是私有的,因此它不能并且会给编译器错误。

有没有办法阻止它尝试默认的Foo构造函数,只是等待Bar构造函数初始化它们?

我想避免使用 new 关键字(这可以解决整个问题)。

修改
看起来人们很难理解这个问题和困境。我会试着解释一下:

我想强制使用Foo(BAZ)构造函数,这意味着任何使用Foo(void)构造函数的尝试都会产生错误。

要隐藏默认构造函数,请将其声明为私有成员。如果有人试图使用默认构造函数Foo(),则会产生故意错误。

不声明默认构造函数,只声明Foo(BAZ)不会阻止编译器创建公共默认构造函数。如果我将其声明为Foo(),则不会出错。到目前为止,它的工作正常并且符合预期。

第二类Bar有两个Foo实例,但是当实例化Bar时,这些Foo成员将使用默认(隐藏)构造函数调用并生成错误。然后在Bar构造函数中,这两个实例将使用正确的公共构造函数Bar(BAZ a,BAZ b)初始化:foo1(a),foo2(b)。这就是我想要的。

有没有办法阻止它在初始化Bar时调用Foo默认构造函数,所以Bar构造函数可以使用正确的Foo构造函数?

解决方案有效,因为永远不会调用默认构造函数:

BAZ a = {...}
Foo *foo1 = new Foo(a);

我希望这更清楚。

EDIT2:已解决 错误不在隐藏的Foo构造函数中,它是隐藏的Bar构造函数,试图使用隐藏的默认Foo构造函数。

Bar(void) : Foo(BAZ{}), Foo(BAZ{}) {}

解决了它。

EDIT3:
真正的问题似乎是在开发工具中。重新启动并手动清除缓存后,它就像C ++ 14标准一样。

2 个答案:

答案 0 :(得分:6)

  

变量foo1和foo2的声明将调用默认值   Foo构造函数

没有。声明这些成员变量表示他们是成员。它没有说明如何构建它们。这是使用它们的类的构造函数的工作。

Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
到目前为止

很好:此构造函数使用构造函数foo1构造foo2Foo(Baz)成员。

Bar(void) {}

这是问题所在:它尝试使用foo1的默认构造函数构建foo2Foo成员。由于该构造函数不是可访问(这是正确的术语;它不是隐藏),因此会出现错误。至少有三种解决方案:

1:

Bar() : foo1(Baz()), foo2(Baz()) {}

这使用了Baz

的构造函数

2:

Bar() = delete;

这使得Bar的默认构造函数不存在,因此它不会尝试使用Foo的默认构造函数。

3:

不要这样做。如果你没有写一个默认的构造函数但是你又编写了另一个,那么编译器就不会生成一个默认的构造函数。

答案 1 :(得分:5)

不要隐藏施工人员。不要在第一时间宣布它们。

const data = [[{a:1,b:2},{c:3,d:4}],{e:5}];

const result = Object.entries(
    Object.assign({}, ...[].concat(...data))
  ).map(([k, v]) => ({ [k]: v }));

console.log(result);
相关问题