为了RAII,我希望将我的类成员保留为值对象,但我也希望将指向其他对象的指针传递给它们的构造函数,以确保它们立即初始化。
我使用构造函数初始化列表初始化它们,但我不确定是否可以使用指向其他类成员的指针初始化类成员。
以下代码使用Apple LLVM 5.1编译器在XCode中按预期编译和工作,但这是我可以使用并信任所有编译器的定义行为吗?而且,这是一般的好习惯还是要避免的事情?除了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的回答之后,我接受了他的建议,并对初始化顺序做了一些阅读。我相信在阅读&#34;最佳实践&#34;注意&#34; C ++ Primer&#34;,[Lippman,Lajoie,&amp; Moo]:
......如果可能,请避免使用成员初始化其他成员。
后来,我心里想到这个想法是错的,但在再次阅读本章之后我才意识到这是完全合法的,尽管应该谨慎使用。该书实际上警告了使用成员初始化其他成员时可能存在的危险。 初始化的顺序取决于成员在类中声明的顺序,而不是它们在初始化列表中的顺序。这意味着如果您向后收到订单,则可能会将未定义的成员传递给另一个成员。
如果你小心的话,那很好,但我想它可能会在以后再回来咬你(或其他人使用你的代码)。
答案 0 :(得分:1)
是的,这是合法的并且在很多地方使用。如果您查看C ++参考文本,您会发现它涉及初始化排序,您可以放心自己这是真的。