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

Max*_*and -4 c++ constructor initialization atmelstudio c++14

我有一个隐藏默认构造函数的类,强制使用带参数的构造函数.另一个类使用该类的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) { ... }
};
Run Code Online (Sandbox Code Playgroud)

最明显的是变量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);
Run Code Online (Sandbox Code Playgroud)

我希望这更清楚.

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

Bar(void) : Foo(BAZ{}), Foo(BAZ{}) {}
Run Code Online (Sandbox Code Playgroud)

解决了它.

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

Pet*_*ker 6

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

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

Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
Run Code Online (Sandbox Code Playgroud)

到目前为止很好:这个构造函数使用构造函数构造foo1foo2成员Foo(Baz).

Bar(void) {}
Run Code Online (Sandbox Code Playgroud)

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

1:

Bar() : foo1(Baz()), foo2(Baz()) {}
Run Code Online (Sandbox Code Playgroud)

这使用了构造函数Baz.

2:

Bar() = delete;
Run Code Online (Sandbox Code Playgroud)

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

3:

只是不要这样做.如果您没有编写默认构造函数但是您编写了另一个构造函数,则编译器将不会生成默认构造函数.


Seb*_*edl 5

不要隐藏构造函数.不要首先声明它们.

typedef struct { ... } BAZ;

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

class Bar {
  private:
    Foo foo1;
    Foo foo2;

  public:
    Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
};
Run Code Online (Sandbox Code Playgroud)

  • 或者,对于C++ 11,显式删除它们,`public:Foo()= delete;`.这将告诉人们默认构造函数是明确的,故意不可用的. (2认同)