函数重载
要求条件:
1.参数个数不同
2.参数类型不同
3.函数的返回值不能决定函数是否被重载
4.作用域必须相同
引用
引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。
优点:
1.不需要分配内存
2.同普通变量一样,使用成员运算符 '.' 访问成员
引用必须初始化
引用只能被赋值一次(只能作为一个变量的别名)
c++函数参数传递方式:传值、传地址、传引用
构造函数
构造函数是在类中说明的特殊的成员函数。
构造函数是在创建对象时,用指定的值初始化对象的数据成员,构造函数提供了初始化对象的一种简单的方法。
系统约定构造函数名必须与类名相同。
构造函数可以带参数、可以重载,同时没有返回值。\
class A{
float x,y;
public:
A(float a,float b)
{x = a; y = b;} //构造函数,初始化对象
float Sum(void)
{return x+y;}
void Set(float a,float b)
{x=a; y=b;}
void Print(void)
{cout<<"x="<<x<<'\t'<<"y="<<y<<endl;}
};
void main(void){
A a1(2.0, 3.0);//定义时调用构造函数初始化
A a2(1.0,2.0);
a2.Set(10.0, 20.0); //利用成员函数重新为对象赋值
a1.Print();
a2.Print();
}
构造函数可以指定参数的缺省值。
若定义的类要定义(实例化)该类的对象时,构造函数必须是公有的成员函数。如果定义的类仅用于派生其它类时,则可将构造函数定义为保护的成员函数。
由于构造函数属于类的成员函数,它对私有数据成员、保护的数据成员和公有的数据成员均能进行初始化。
在定义类时,只要显式定义了一个类的构造函数,则编译器就不产生缺省的构造函数
所有的对象在定义时,必须调用构造函数
不存在没有构造函数的对象!
产生对象时,系统必定要调用构造函数。所以任一对象的构造函数必须唯一。
类的构造函数不唯一\
class A{
float x,y;
public:
A(float a=10,float b=20)
{ x = a; y = b;}
A(){ }
void Print(void){ cout<<x<<'\t'<<y<<endl; }
};
void main(void){
A a1;
A a2(3.0,30.0); // 调用了不同的构造函数
}
析构函数
作用:内存释放
析构函数是成员函数,函数体可写在类体内,也可写在类体外。
析构函数无参,不能发生重载,析构函数不能带有任何参数,不能有返回值,不指定函数类型。
~A(){ }
构造顺序与析构顺序相反,一般后构造的先析构,但与生命周期有关
构造函数和析构函数的调用
1.对于全局定义的对象(在函数外定义的对象),在程序开始执行时,调用构造函数;到程序结束时,调用析构函数
2.对于局部定义的对象(在函数内定义的对象),当程序执行到定义对象的地方时,调用构造函数;在退出对象的作用域时,调用析构函数。
3.用static定义的局部对象,在首次到达对象的定义时调用构造函数;到程序结束时,调用析构函数
4.对于用new运算符动态生成的对象,在产生对象时调用构造函数,只有使用delete运算符来释放对象时,才调用析构函数。若不使用delete来撤消动态生成的对象,程序结束时,对象仍存在,并占用相应的存储空间,即系统不能自动地调用析构函数来撤消动态生成的对象。
注意:对于用new运算符动态生成的对象,在产生对象时调用构造函数,只有使用delete运算符来释放对象时,才调用析构函数。若不使用delete来撤消动态生成的对象,程序结束时,对象仍存在,并占用相应的存储空间,即系统不能自动地调用析构函数来撤消动态生成的对象。
pal = new a[3];
delete []pal;
因此,在对象实例化过程中,如果用new运算符开辟了空间,则推荐在类中定义一个析构函数,并在析构函数中使用delete删除由new分配的内存空间。因为在撤消对象时,系统自动收回为对象所分配的存储空间,而不能自动收回由new分配的动态存储空间。
隐式构造
同类型的对象可以相互赋值,相当于类中的数据成员相互赋值;
如果直接将数据赋给对象,所赋入的数据需要类型转换为一个对象,这种转换需要调用构造函数。转换过程叫隐式构造
注意:当构造函数只有一个参数时(或只需要传递一个参数),构造对象时可以用= 直接赋值。
拷贝构造
可以在定义一个对象的时候用另一个对象为其初始化,即构造函数的参数是另一个对象的引用,这种构造函数称为拷贝构造函数。
class A{
float x,y;
public:
A(float a=0, float b=0)
{x=a; y=b;}
A(A &a)
{x=a.x; y=a.y;}
};
void main(void){
A a1(1.0,2.0);
A a2(a1);
}
如果没有定义完成拷贝功能的构造函数,编译器自动生成一个隐含的完成拷贝功能的构造函数,依次完成类中对应数据成员的拷贝。\ 但是,当类中的数据成员中具有指针类型的成员,进行赋初值时,必须在类中显式地定义一个完成拷贝功能的构造函数,以便正确实现数据成员的复制。否则应用默认拷贝构造会引起浅拷贝,造成系统运行错误。
名词解释:浅拷贝
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果对象的数据成员包括指向堆空间的指针,就不能使用这种拷贝方式,因为两个对象都拥有同一个资源,对象析构时,该资源将经历两次资源返还,此时必须自定义深拷贝构造函数,为创建的对象分配堆空间,否则会出现动态分配的指针变量悬空的情况