第三章
构造函数
1. 构造函数不需要用户调用它,而是建立对象的时候自动执行。
2. 可以用一个类对象来初始化另一个类对象,如:
Time t1;
Time t2=t1;
3. 如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,知识这个构造函数体是空的,也没有参数,不执行任何操作。一个类只有一个默认构造函数。
4. 用参数初始化列表对数据成员初始化,如下:
Box::Box(int h,int w):height(h),width(w){ }
5. 构造函数重载
参数个数或参数类型不同,如下:
Box::Box(int h);
Box::Box(int h,int w);
析构函数
1. 如果一个函数中定义了一个对象,当这个函数被调用结束时,对象应被释放,在对象释放前自动执行析构函数。
2. 静态局部变量在函数调用结束时对象并不是释放,只有在main函数结束或调用exit函数结束程序时,才调用static局部变量的析构函数。
3. 如果用new建立一个对象,当用delete释放该对象时,先调用该对象的析构函数。
4. 析构函数并不是删除对象,而是在撤销对象占用内存之前进行清理工作,使这部分内存可以被程序分配给新对象使用。
5. 析构函数没有函数参数,因此不能被重载。
6. 先构造的后析构。相当于栈,先进后出。
对象数组
1. Student stud [50]
对象数组的每一个元素都是同类的对象。
如果有50个元素,则需要调用50次构造函数。
2. 如果构造函数只有一个参数,在定义数组时可以直接初始化。如下:
Student stud [3] ={ 60,70 ,80 };
3. Student stud [3] ={
Student(1001,18,87),
Student(1002,34,14),
Student(1003,89,47),
}
对象指针
1. 一个对象存储空间的起始地址就是对象的指针。
Time *p;
Time t1;
p=&t1;
(*p).hour 等价于 p->hour
2. 指向成员函数的指针
三点需要相互匹配:
(1). 函数参数的类型和参数个数
(2). 函数返回值类型
(3). 所属的类
如下:
void(*p)()
p=fun; //将fun函数的入口地址赋给指针p
(*p)();
显然不符合第三点,p与类无关,因此不能在类外直接用成员函数名作为函数入口地址去调用成员函数。
修改如下:
void(Time::*p)(); //定义p为指向Time类中公共成员函数的指针变量。
p=&Time::get_time;
3. 指向当前对象的this指针
在每个成员函数中都包含一个特殊的指针,this指针。它是指向本类对象的指针,它的值是当前被调用的成员函数所在的对象的起始地址。
例如:当调用成员函数a.volume()时,编译系统就把对象a的起始地址赋给this指针。
int Box::volume(){ returun (height*width*length) }
a.volume();
C++把它处理为
int Box::volume(){ returun (this->height*this->width*this->length) }
a.volume(&a);
由于this指向a,所以相当于:(a.height)*(a.width)*(a.length)
常对象
1. Time const t1(12,34,56); / const Time t1(12,34,56);
在t1的生命周期中,对象t1的所有数据成员的值都不能被修改
2. 常对象只能调用常成员函数,不能调用该对象的普通成员函数(除了构造和析构函数)
常对象成员
1. 常数据成员:只能通过构造函数的参数初始化表对常数据成员进行初始化,任何其他函数都不能对常数据成员赋值。
2. 常成员函数:只能引用本类的数据成员,不能修改。不能调用另一个非const成员函数。
void get_time() const;
指向对象的常指针
形式: 类名 * const 指针变量名
Time * const ptr1;
注意:指向对象的常指针变量的值不能改变,始终指向同一个对象,但可以改变其所指向对象的值。
指向常对象的指针
const char *ptr;
1. 如果一个变量已经声明为常变量,只能用指向常变量的指针来指向它。如下:
const char c[]=”boy”;
const char * P1;
p1=c; //合法
char *p2 =c; //错误,p2不是指向常变量的指针。
2. 指向常变量的指针也可以指向非const的变量,但是不能通过指针来修改变量的值,如下:
char c=’a’;
const char * p;
p=&c;
*p=’b’; //错误
c=’b’; //合法
3. 指向常变量的指针既可以指向const变量也可以指向非const变量,而指向非const变量的指针只能指向非const变量。
4. 规则:当希望在调用函数时对象的值不被修改,就应当把形参定义为指向常对象的指针,同时用对象的地址作为实参。
对象的复制
形式:类名 对象2(对象1)
定义语句: 类名(类名 & 对象){...},例如:Box(Box &b){...}
静态数据成员
如果希望各对象中的数据成员的值是一样的,就把它定义为静态数据成员。
1. 它为各对象所共有,在内存中只占一份空间。
2. 静态数据成员只能在类体外进行初始化。不能用参数初始化表对静态数据成员初始化。
如果未初始化,系统自动设置为0。
int Box::height=10;
3. 静态数据成员不属于对象,而是属于类的。
4. 有了静态数据成员,各对象之间的数据有了沟通的渠道,实现数据共享,可以不使用全局变量。全局变量破坏了封装的原则,不符合面向对象程序的要求。
静态成员函数
1. 在类外调用公用的静态成员函数,形式如下:
Box::volume();
2. 静态成员函数没有this指针,因此不能访问本类中的非静态成员。
在C++中,静态成员函数主要是用来访问静态数据成员。
友元函数
1. friend函数不仅可以是一般函数,也可以是另一个类中的成员函数。
类模板
1. 类模板是类的抽象,类是类模板的实例。
2. template<class 类型参数名>
class 类模板名{
......
}
int main{
类模板名 <实际类型名> 对象名(参数表);
......
}