标签:oid turn color include 程序 class com 输出 bar
如果一个类没有自己的构造函数,编译器会在需要的时候为其合成一个出来,俗称:合成默认构造函数。但是请注意是在需要的时候,并不是所有情况。
请看下面代码:
1 #include<iostream> 2 using namespace std; 3 class Foo { 4 public: 5 int val; 6 Foo *pnext; 7 }; 8 9 void foo_bar() 10 { 11 Foo bar; 12 if (bar.val || bar.pnext) 13 { 14 cout << "数据被编译器初始化了" << endl; 15 } 16 } 17 int main() 18 { 19 foo_bar(); 20 while (1); 21 return 0; 22 }
输出会报错:
分析:对于上述情况,编译器并不会认为是需要的,因为初始化数据成员应该是程序员的职责,而并非是编译器的职责。所以必须自己写一个构造函数出来为其数据成员进行初始化。
假设编译器认为需要的时候到了,这时候为其合成了一个默认构造函数出来,也不会对该类的数据成员进行初始化,因为这并不是编译器的职责。比如下面代码:
1 #include<iostream> 2 using namespace std; 3 class Foo { 4 public: 5 Foo(){ 6 cout << "默认构造函数被调用" << endl; 7 }; 8 }; 9 10 class Bar { 11 public: 12 Foo foo; 13 char *str; 14 }; 15 void foo_bar() 16 { 17 Bar bar; 18 if (bar.str) 19 { 20 cout << "类Bar的数据成员被编译器初始化了" << endl; 21 } 22 } 23 int main() 24 { 25 foo_bar(); 26 while (1); 27 return 0; 28 }
输出:
和第一种情况比,这时候的编译器没有报错,但是编译器还是没有为数据成员进行初始化。
上面的代码引出第一种编译器会自动合成默认构造函数的情况:如果一个类中包含另一个类,对于后者,有自己定义的默认构造函数。而前者没有,那么此时编译器会为其合成一个出来,但是合成的目的仅仅只是为了调用后者的默认构造函数,对于自己类的数据成员,必须由程序员自己初始化。
所以合理的应该是这样的:
1 #include<iostream> 2 using namespace std; 3 class Foo { 4 public: 5 Foo() { 6 cout << "默认构造函数被调用" << endl; 7 }; 8 9 }; 10 11 class Bar { 12 public: 13 Foo foo; 14 char *str; 15 Bar() 16 { 17 //编译器自动安插代码段Foo::Foo()的内容... 18 str = new char;//程序员为自己的数据成员赋值。 19 } 20 21 }; 22 void foo_bar() 23 { 24 Bar bar; 25 if (bar.str) 26 { 27 cout << "类Bar的数据成员被编译器初始化了" << endl; 28 } 29 } 30 int main() 31 { 32 foo_bar(); 33 while (1); 34 return 0; 35 }
输出:
分析:
对于类Bar,现在有了自己的构造函数,虽然没有显示的定义类Foo的,编译器还是为其合成了一个出来,因为编译器认为这是需要的时候,这种需要仅仅是需要调用类Foo的默认构造函数,但是对于自己的数据成员,它依然置之不顾。
标签:oid turn color include 程序 class com 输出 bar
原文地址:https://www.cnblogs.com/SunShine-gzw/p/13179856.html