【问题标题】:C++ How to initialize members with hidden default constructors?C ++如何使用隐藏的默认构造函数初始化成员?
【发布时间】:2017-12-01 18:37:07
【问题描述】:

我有一个带有隐藏默认构造函数的类来强制使用带参数的构造函数。另一个类正在使用该类的 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构造函数?

new 解决方案有效,因为从不调用默认构造函数:

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

我希望这会让它更清楚。

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

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

解决了。

EDIT3:
真正的问题似乎出在开发工具上。重新启动并手动清除缓存后,它按照 C++14 标准的预期工作。

【问题讨论】:

  • 如果您不想使用它,为什么要定义它?
  • 仅声明 any c'tor 的行为会阻止生成隐式默认值。那是 C++ 101。
  • 不要在 C++ 中做 typedef struct 废话,这是 C 的一个坏习惯。
  • 顺便说一句,我不明白使用new 会如何解决任何问题
  • @MaxKielland 没有错误?当我这样做时不会发生这种情况:ideone.com/ZHBwlK

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


【解决方案1】:

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

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

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

到目前为止还不错:此构造函数使用构造函数 Foo(Baz) 构造 foo1foo2 成员。

Bar(void) {}

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

1:

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

这使用了接受Baz的构造函数。

2:

Bar() = delete;

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

3:

只是不要这样做。如果你不写默认构造函数,但你写了另一个,编译器不会生成默认构造函数。

【讨论】:

  • 当你回答时我得出了同样的结论:) 这个编译器似乎总是声明一个默认构造函数,但我会尝试使用 delete 语句。
  • Foo(void) = delete;在我重新启动并清除缓存后工作。这似乎是开发工具中的部分缓存问题。
【解决方案2】:

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

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) { ... }
};

【讨论】:

  • 或者,对于 C++11,显式删除它们,public: Foo() = delete;。这会告诉人们默认构造函数是明确的、有意的不可用的。
  • OMFG。我不知道可以在类中以这种方式构造具有特殊构造函数的成员变量。我花了数年时间不必要地创建指针。我觉得如此愚蠢。
  • 好像是开发工具的缓存问题。重新启动和缓存清理后,它按预期工作。
猜你喜欢
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-28
  • 2018-11-24
  • 2016-04-05
  • 1970-01-01
相关资源
最近更新 更多