初始化列表——可以用同一类的其他成员初始化成员吗?
Initialization Lists - Can I initialize members with other members of the same class?
为了RAII,我想保持我的类成员作为值对象,但我也想把指向其他对象的指针传递给它们的构造函数,以确保它们被立即初始化。
我使用构造函数初始化列表初始化它们,但我不确定是否可以用指向其他类成员的指针初始化类成员。
以下代码在XCode中编译并按预期工作,使用Apple LLVM 5.1编译器,但这是我可以使用并信任所有编译器的定义行为吗?这是一种普遍的好做法,还是要避免的做法?除了init()
函数,还有其他方法可以实现这个吗?
class Foo {
public:
int value;
Foo() {}
void woot() {
std::cout << "A Foo says WOOT my value is: " << value << std::endl;
}
};
class Bar {
public:
Foo* foo;
int value;
Bar( Foo* f ) : foo(f) {
foo->value = 66;
foo->woot();
}
void woot() {
std::cout << "A Bar says WOOT my value is: " << value << std::endl;
}
};
class Boo {
public:
Foo* foo;
Bar* bar;
int value;
// Passing members into constructors of other members:
Boo( Foo* f, Bar* b ) : foo(f), bar(b) {
foo->value = 77;
foo->woot();
bar->value = 88;
bar->woot();
}
};
class Yaa {
public:
Foo foo;
Bar bar;
Boo boo;
Yaa() : bar(&foo), boo(&foo, &bar) {
woot();
}
void woot() {
std::cout << "A Yaa says WOOT, my children say woot:" << std::endl;
foo.woot();
bar.woot();
}
};
void testInitialisation() {
Yaa f;
}
// ...
testInitialisation();
// Output:
// A Foo says WOOT my value is: 66
// A Foo says WOOT my value is: 77
// A Bar says WOOT my value is: 88
// A Yaa says WOOT, my children say woot:
// A Foo says WOOT my value is: 77
// A Bar says WOOT my value is: 88
编辑/注:在接受@Wes Hardaker的回答后,我接受了他的建议,并对初始化顺序做了更多的阅读。我相信我最初的困惑是在阅读了"c++入门"中的"最佳实践"注释后产生的,[Lippman, Lajoie, &Moo]:
…在可能的情况下,避免使用成员初始化其他成员。
后来,我有这个想法,在我的脑海里,这是错误的,但在阅读章节再次我意识到这是完全合法的,虽然应该谨慎使用。这本书实际上警告了使用成员初始化其他成员时的潜在危险。初始化顺序由成员在类中声明的顺序决定,而不是由它们在初始化列表中的顺序决定。这意味着如果顺序颠倒,则可以将未定义成员传递给另一个成员。
所以,如果你很小心,这是好的,但我猜它可能会回来咬你(或其他人使用你的代码)以后。
是的,这是合法的,并且在很多地方使用。如果你看一下c++的参考文献,你会发现它讨论了初始化顺序,在那里你可以确信它是正确的。
相关文章:
- 为什么在C++中首先初始化成员类
- 是否可以防止省略聚合初始化成员?
- 正在复制具有未初始化成员的结构
- 使用大括号或括号初始化成员变量
- C++结构:强制初始化成员?
- C++中未初始化成员布尔变量的默认值是多少?
- 使用默认值初始化成员引用
- 在构造函数中初始化成员时,是否应该在成员上使用 std::move?
- C++使用 { } 初始化成员变量
- 如何根据构造函数参数使用超类类型初始化成员变量?
- OpenGL C++:VBO 的结构包装器不会初始化成员
- 有没有办法在Brace中初始化成员
- 从现有 istream 或类本身创建的 istream 初始化成员 istream
- 从其后声明的另一个成员数据初始化成员数据是否为未定义行为
- 通常应用方法,使用带有构造函数委托的 SFINAE 通过类模板的构造函数初始化成员
- 如何在嵌套类中初始化成员?C
- 是否可以在构造函数主体中初始化成员变量,而不是初始值设定项列表
- 编译器错误,因为构造函数必须显式初始化成员
- 如何使用成员函数初始化成员函数指针
- C 如何使用隐藏的默认构造函数初始化成员