C++:如何使用初始化列表初始化内部结构的成员?

3
这实际上是两个问题,如下所示:
目前我有一些公共的内部帮助结构体(严格用作一个对象传递数据),在构造类的实例时,我尝试使用初始化列表而不是赋值,但编译器抱怨单个结构体成员,所以我添加了结构体的构造函数...但这似乎是错误的方向。
有没有一种方法可以在初始化列表中初始化结构体而不使用构造函数?
这些辅助程序是否更适合作为外部类?
```c++ class Foo { public: struct Bar { double mass; std::pair gravMod; std::pair position; std::pair velocity; bool falling; Bar() : mass(0.0), gravMod(std::make_pair(0.0, 0.0)), position(std::make_pair(0.0, 0.0)), velocity(std::make_pair(0.0, 0.0)), falling(false) { }; Bar(double _mass, std::pair _gravMod, std::pair _position, std::pair _velocity, bool _falling) : mass(_mass), gravMod(_gravMod), position(_position), velocity(_velocity), falling(_falling) { } Bar(const Bar& other) : mass(other.mass), gravMod(other.gravMod), position(other.position), velocity(other.velocity), falling(other.falling) { } };
struct Baz { std::pair acceleration; std::pair force; Baz() : acceleration(std::make_pair(0.0, 0.0)), force(std::make_pair(0.0, 0.0)) { } Baz(std::pair _acceleration, std::pair _force) : acceleration(_acceleration), force(_force) { } Baz(const Baz& other) : acceleration(other.acceleration), force(other.force) { } }; protected: private: Bar _currBar; Bar _prevBar; Baz _currBaz; Baz _prevBaz; }; ```
编辑:
示例及其相关错误:
```c++ Foo::Foo() : _currBar{0.0, std::make_pair(0.0, 0.0), std::make_pair(0.0, 0.0), std::make_pair(0.0, 0.0), false}, _currBaz{std::make_pair(0.0, 0.0), std::make_pair(0.0, 0.0)} { } ```

_currBar{ 抛出错误: 期望 '('. 第一个 } 抛出错误: 期望';'.

 
Foo::Foo() : _currBar.mass(0.0), _currBar.gravMod(std::make_pair(0.0, 0.0)), _currBar.position(std::make_pair(0.0, 0.0)), _currBar.velocity(std::make_pair(0.0, 0.0)), _currBar.falling(false) { }
 

第一个 _currBar. 抛出错误: 期望 '('. 所有其余的 _currBar. 都抛出错误: 成员 'Foo::_currBar' 已经被初始化。.


2
我给结构体添加了构造函数...但这似乎是我走错了方向。如果你问我,那听起来像是一条不错的路。 - James McNellis
你为什么认为添加构造函数会走错路? - KillianDS
如果不在构造函数内部初始化这些结构的每个实例中的成员,您将如何进行初始化? - Praetorian
编译器具体抱怨了什么?你的代码有哪些你不喜欢的地方? - Tom
3个回答

5
在C++03中,没有办法初始化嵌套结构的个别字段,也没有办法初始化嵌套数组的个别字段。在C++0x(现在是C++11,我猜),它们放宽了这个限制,你可以使用以下语法初始化嵌套结构:
Foo::Foo() : _currBar{fieldOneValue, fieldTwoValue, /* ... */, fieldNValue}, /* ... etc ... */

在等待更多编译器完全支持此功能之前,向嵌套的struct添加构造函数是完全可行的选择。


建议使用的数组初始化语法在VS2010 MSVC10中无法正常工作。请参见编辑说明。 - Casey
@Casey- 我从未暗示它有效。上述代码在C++0x标准中提出,这意味着几年后编译器将支持它。在那之前,你需要在辅助结构体中放置构造函数才能使其正常工作。 - templatetypedef

0

原则上可以不使用构造函数:

Foo::Foo(): _currBar(), _prevBar(), _currBaz(), _prevBaz() {}

这个语法会将没有构造函数的对象进行零初始化(将所有字段设置为0 / 调用它们的默认构造函数)。

如果你想要带参数的构造函数,可以使用一个辅助函数:

Bar make_bar(double mass, std::pair<double, double> gravMod, std::pair<double, double> position, std::pair<double, double> velocity, bool falling)
{
    Bar bar = { mass, gravMod, position, velocity, falling };
    return bar;
}

Foo::Foo(args...): _currBar(make_bar(args...)), ...

无论如何,您不需要添加复制构造函数。编译器将生成一个复制构造函数,它将完全执行此操作。
(顺便说一下,当数学向量类更合适时,我可能不会使用std :: pair。我假设像position这样的东西可以使用名为x和y的属性而不是first和second。)

0

只要您保持以下方式,所使用的方法就没有问题:

严格用于作为一个对象传递数据

当决定使用结构体还是类时,需要问自己的问题是:这个对象是否存在一个不变量?不变量是指构成对象有效状态的描述。如果您可以定义一个不变量,则可以定义一个无效状态,并且应通过成员函数提供对内部成员变量的访问,以确保维护有效状态。最好使用类来执行此操作。但是,如果任何旧状态都可以使用,则使用结构。

您的构造函数仅提供合理的默认值,而不试图维护有效状态,因此在结构中使用它们是没有问题的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接