类成员初始化
一、调用无参构造函数
代码如下:(在类中实例化另一个类)
1 #include<iostream> 2 #include <string> 3 4 5 using namespace std; 6 7 class StudentID 8 { 9 int value; 10 public: 11 StudentID() 12 { 13 static int nextStudentID = 0; 14 value = ++nextStudentID; 15 cout<<"Assigning student id "<<value <<endl; 16 } 17 }; 18 19 class Student 20 { 21 string name; 22 StudentID id; // 这里是在类中定义另一个类 23 public: 24 Student(string n = "noName") 25 { 26 cout<<"Constructing student " +n <<endl; 27 name = n; 28 } 29 }; 30 31 32 int main() 33 { 34 Student s("Randy"); 35 cout<<sizeof(s)<<endl; 36 return 0; 37 }
是如何调用构造函数的?运行结果?
反汇编主要代码:
1 // 这是student类的构造函数 2 3 004016F9 mov ecx,dword ptr [ebp-10h] 4 004016FC add ecx,10h 5 004016FF call @ILT+400(StudentID::StudentID)(00401195) // 在执行函数体前,现调用StudentID的构造函数 6 25: { 7 26: cout<<"Constructing student " +n <<endl; 8 ..... 9 ..... 10 }
注意:
C++ 的类机制对于含有对象成员的类对象的构造定了一些规则,对于源代码34行语句,其内部执行次序是这样的:
1、现分配学生雷对象s的空间,调用Student构造函数;
2、在Student构造函数体尚未执行时,由于看到了类的对象成员id,转而去调用学好累的无参构造函数,相当于去执行定义语句:
StudentID id;
3、执行完StudentID类的构造函数体,输出结果,返回到Student构造函数
4、执行Student类的构造函数体,输出结果,完成全部构造工作。
二、自定义构造函数(可以初始化成员变量)
1 #include<iostream> 2 #include <string> 3 4 using namespace std; 5 6 class StudentID 7 { 8 int value; 9 public: 10 StudentID(int id = 0) 11 { 12 value = id; 13 cout<<"Assigning student id "<<value <<endl; 14 } 15 }; 16 17 class Student 18 { 19 string name; 20 StudentID id; 21 public: 22 Student(string n = "noName",int ssID = 0) 23 { 24 cout<<"Constructing student " +n <<endl; 25 name = n; 26 // id.value = ssID;因为value在类中是private属性,是不能直接访问的.... 27 StudentID id(ssID); // 这里是局部对象,等这个函数体结束了,他也就结束了...... 28 } 29 }; 30 31 int main() 32 { 33 Student s("Randy",58); 34 cout<<sizeof(s)<<endl; 35 return 0; 36 }
这就产生了初始化的问题,此外,常量成员和引用成员在构造时,也存在初始化的问题:
1 class Silly 2 { 3 const int ten; // 常量成员 4 int &ra; // 引用成员 5 public: 6 Silly(int x,int &a) 7 { 8 ten = 10; // 破坏常量操作语法 9 ra = a; // 仅表示a的值赋给引用 ra; 10 } 11 }
问题1:常量不能做左值 2、引用只能在创建时进行初始化.....
由上面的问题引出一下的解答....
三、成员的初始化
在构造函数的参数列表右括号后面,花括号前面,可以用冒号引出构造函数的调用表,该调用表可以省略类型名称,但却行创建对象之职......
成员变量初始化顺序,与在定义中定义顺序相同!!!!
1 #include<iostream> 2 #include <string> 3 4 using namespace std; 5 6 class StudentID 7 { 8 int value; 9 public: 10 StudentID(int id = 0) 11 { 12 value = id; 13 cout<<"Assigning student id "<<value <<endl; 14 } 15 }; 16 17 class Student 18 { 19 string name; 20 StudentID id; 21 public: 22 Student(string n = "noName",int ssID = 0):id(ssID),name(n) 23 { 24 cout<<"Constructing student " +n <<endl; 25 26 } 27 }; 28 29 int main() 30 { 31 Student s("Randy",58); 32 Student t("Jenny"); 33 return 0; 34 }
按照以往知识,以对象名引导构造函数必须跟在类型名后面,只在对象定义中被允许。而且,如果已经创建了一个对象,则该对象不能一函数调用的形式出现。对象只能通过点操作符绑定飞构造函数的其他成员函数进行操作:
1 PPoint d(3,2) 2 cout<<d(6,8); // 错 3 cout<<d.angle();
特例: 构造函数的构造参数列表破例采用了对象名引导构造函数调用的形式。
另外,第22行中写成id(ssID)的形式转而去调用StudentID的构造函数,目的是不要调用无参构造函数,而按构造参数列表中说明的参数要求去调用。相当于:
StudentID id(ssID);
另外,对于常量成员和引用成员也可以构造参数表的方式解决
1 class Silly 2 { 3 const int ten; 4 int &ra; 5 public: 6 Silly(int x,int &a):ten(10),ra(a) {} 7 }