【this指针】:
1.每个成员函数都有一个指针形参,它的名字是固定的,成为this指针,this指针是隐式的,(构造函数比较特殊,没有这个隐含this形参)。
2.类型: 类类型* const
3.this指针并不是对象本身的一部分,不影响sizeof的结果
4.this指针是”类成员函数”的第一个默认隐含参数,编译器自动维护传递,类编写者不能显式传递
5.只有在类的非静态成员函数中才可以使用this指针,其它任何函数都不可以
1.【构造函数】
构造函数(constructor)是一个特殊的成员函数,名字与类名相同,创建类类型对象时,由编译器自动调用,在对象的生命周期内只调用一次,保证每个数据成员都有
一个合适的初始值
构造函数是特殊的成员函数,其特征如下:
1. 函数名与类名相同。
2. 无返回值。
3. 对象构造(对象实例化)时系统自动调用对应的构造函数。且在对象的声明周期内仅调用
一次.
4. 构造函数可以重载。
5. 构造函数可以在类中定义,也可以在类外定义。
6. 如果类定义中没有给出构造函数,则C++编译器自动产生一个缺省的构造函数,但只要我们定义了一个构造函数,系统就不会自动
生成缺省的构造函数。
7. 无参的构造函数和全缺省值的构造函数都认为是缺省构造函数,并且缺省的构造函数只能有一个。
8.构造函数不能为虚函数
Date(int year = 1900, int month = 1, int day = 1) //全缺省构造函数
{
_year = year;
_month = month;
_day = day;
}
2.【拷贝构造函数】
只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为拷贝构造函数。拷贝构造函数是特殊的构造函数,创建对象时使用已存在的同类对象来进行初始化,由编译器自动调用
特征:
1. 拷贝构造函数其实是一个构造函数的重载。构造函数的性质拷贝构造均满足
2. 拷贝构造函数的参数必须使用引用传参,指针也不行,使用传值方式会引发无穷递归调用。(把形参复制到实参会调用拷贝构造,如果进行值传递,就会在拷贝构造函数内调用拷贝构造函数。)这里传引用,并不是为了减少内存拷贝。
举个例子:
Date s2(s1);
拷贝构造函数:Date (Date t); 这里进行传值的话,因为要构造 t 就会产生Date t (s1),再将s1传值给拷贝构造函数,又因为同样的原因,再次产生Date t (s1);
3. 若未显示定义,系统会默认缺省的拷贝构造函数。缺省的拷贝构造函数会依次对拷贝类成员进行初始化。
构造函数使用的场景:
1>显式或隐式地用同类型的一个对象来初始化另外一个对象。如:Date a; Date b(a);
2>作为实参传递给一个函数。
3>在函数体内返回一个对象时,也会调用返回值类型的拷贝构造函数.。
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
3.【析构函数】
当一个对象的生命周期结束时,C++编译系统会自动调用一个成员函数,这个特殊的成员函数即析构函数(destructor)
构造函数是特殊的成员函数,其特征如下:
1. 析构函数在类名加上字符~。
2. 析构函数无参数无返回值。
3. 一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
5. 注意析构函数体内并不是删除对象,而是做一些清理工作。
class Array
{
public :
Array (int size)
{
_ptr = (int *)malloc( size*sizeof (int));
assert(_ptr);
}
// 这里需要析构函数释放空间
~ Array ()
{
if (_ptr )
{
free(_ptr );
_ptr = 0;
}
}
private :
int* _ptr ;
};
4.【运算符重载】
为了增强程序的可读性,C++支持运算符重载。
运算符重载特征:
1. operator+合法的运算符构成函数名(重载<运算符的函数名:operator<)。
2. 重载运算符以后,不能改变运算符的优先级/结合性/操作数个数。
5个C++不能重载的运算符: .* :: sizeof ? : .
赋值运算符重载:
拷贝构造函数是创建的对象,使用一个已有对象来初始化这个准备创建的对象。
赋值运算符的重载是对一个已存在的对象进行拷贝赋值
Date& operator=(const Date& d) //赋值运算符的重载 >> 返回引用,防止连续赋值
{
if (this != &d) //检测是否是自身赋值
{
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
}
return *this;
}
类的成员变量有两种初始化方式:
1. 初始化列表。
2. 构造函数体内进行赋值。
初始化列表以一个冒号开始,接着一个逗号分隔数据列表,每个数据成员都放在一个括号中进行初始化。尽量使用初始化列表进行初始化,因为它更高效
哪些成员变量必须放在初始化列表里面?
1. 常量成员变量。(常量创建时必须初始化)
2. 引用类型成员变量。(引用创建时必须初始化)
3. 类类型成员(该类有非缺省的构造函数)
成员变量按声明顺序依次初始化,而非初始化列表出现的顺序
取地址操作符的重载和const取地址操作符的重载: 一般不建议重载。系统默认生成的足够使用。
自己写可以设置是否允许取得类的地址,以此防止其他函数通过取地址修改原本不应被修改的类的成员。
什么情况下类才会真正的合成构造函数、拷贝构造函数及赋值运算符的重载?
类的类成员有缺省的构造函数,因为要构造该类成员就必调用该类的构造函数,且该类的初始化必须放在初始化列表中。
当成员为内置类型时,类不会合成默认的构造函数:
类的类成员有缺省的构造函数,类会自动合成构造函数。