c++类和对象之对象的初始化
1、构造函数概述
在c++程序中对象的初始化是⼀个不可缺少⽽⼗分重要的内容。为了对对象进⾏初始化,c++提供了构造函数来处理对象的初始化,构造函数是⼀种特殊的成员函数,与其他函数不同,构造函数时在建⽴对象时⾃动执⾏。
构造函数的作⽤:对象的初始化
构造函数的调⽤:由编译器⾃动调⽤
构造函数的调⽤时机:在创建对象时,系统会为该对象分配内存空间,并调⽤构造函数进⾏初始化
构造函数的要求:函数名与类名相同(以便编译器能够识别它,把它当作构造函数来处理),没有类型,不返回任何值。
注意:
1.如果⽤户没有⾃⼰定义构造函数,则c++系统会⾃动⽣成⼀个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执⾏初始化操作。
2.构造函数可以重载
3.构造函数可以有默认参数
4.构造函数的重载与默认⼀般不同时使⽤,以免造成⼆义性问题。
5.如果⽤户⾃定义构造函数,系统不会指⾃动产⽣默认构造,但是会产⽣拷贝构造。
6.如果⽤户⾃定义拷贝构造,系统不会提供其他构造函数
2、构造函数的分类及调⽤
按参数分为
1.⽆参构造函数
2.有参构造函数
按类型分为
1.普通构造
2.拷贝构造
三种调⽤
1.括号发
2.显⽰发
3.隐⼠转换法
#include <iostream>
using namespace std;
class person
{
public:
person()
{
cout <<"person的⽆参构造调⽤"<< endl;
}
person(int a)
{
age = a;
cout <<"person的有参构造调⽤"<< endl;
}
person(const person &p)
{
age =p.age;
cout <<"person的拷贝构造调⽤"<< endl;
}
~person()
{
cout <<"person的析构调⽤"<< endl;
}
int age;
};
void test01()
{
//括号法
person p1;//注意不要加(),否则会被认为函数声明
person p2(100);
person p3(p2);
//显⽰法
person p4;//注意不要加(),否则会被认为函数声明
person p5=person(100);//如果将person(100)单独拿出来,就是匿名对象
person p6=person(p5);
//隐⼠转换法法
person p7;//注意不要加(),否则会被认为函数声明
person p8=100;//person p8=person(100);
person p9=p8;//person p9 = person(p8);
}
int main()
{
test01();
return0;
}
3、⽤初始化列表来初始化对象
构造函数可以被重载person(int a):age(a)
{
age = a;
cout <<"person的有参构造调⽤"<< endl;
}
注意:⽤初始化列表进⾏初始化时,数据成员不能是数组,如果数据成员包含数组,则必须⽤函数体对数组进⾏初始化。
4、构造函数的重载
说明:
1.在建⽴对象时不必给出实参的构造函数称为默认构造函数。显然⽆参构造函数属于默认构造函数,⼀个类只能有⼀个默认构造函数,如果⽤户没有⾃定义构造函数,系统会⾃动产⽣⼀个默认构造函数,但是它的函数体是空的,不起初始化作⽤。
2.如果在建⽴对象时选⽤的时⽆参构造,则要注意其写法。
person p4;//注意不要加(),否则会被认为函数声明
3.尽管在⼀个类中可以有多个构造函数,但是对于每⼀个对象来说,只执⾏其中⼀个构造函数,并⾮每个构造函数都会被执⾏。
5、使⽤默认参数的构造函数
说明:
1.应该在构造函数声明的地⽅指定默认值,⽽不是只在定义构造函数时指定默认值。
2.在声明构造函数时,形参名称可以省略
3.如果全部参数都有默认值,则不⽤在写⽆参构造。
4.⼀般在使⽤默认参数的构造函数后,不应再使⽤函数重载,以免产⽣⼆义性问题。
6、对象的赋值和复制
⼀.对象的赋值
对象的赋值与普通变量的⼀样,赋值的⼀般形式
对象名1=对象名2;
注意这⾥的=本来只可以对单个变量的赋值,但是由于c++提供了运算符重载功能,使⽤=可以⽤于两个同类对象的赋值。
说明:
1.对象的赋值只对其中数据成员赋值,⽽不对数据对象赋值。
2.类的数据成员中不能包括动态分配的数据,否则在赋值时可能会出现严重后果。
⼆.对象的复制
复制的⼀般形式
类名 对象2(对象1);等价于
类名 对象2=对象1;
对象的复制是调⽤拷贝构造函数实现的。
总结:
对象赋值是对⼀个已经存在的对象赋值,因此必须先定义被赋值的对象,才能进⾏赋值。⽽对象的复制则是从⽆到有地建⽴⼀个新对象,并使它与⼀个已有对象完全相同(包括对象的结构和成员的值)
7、拷贝构造的调⽤时机
1.使⽤⼀个已经创建好的对象来初始化⼀个新对象
2.当函数的参数为类的对象
void fun(Person p){}
int main()
{
Person p1(10);
fun(p1);
return0;
}
3.函数的返回值时类对象
person fun()
{
person p(10);
rtunrn p;
}
int main()
{
person p1;
p1=fun();
return0;
}
8、深拷贝与浅拷贝
浅拷贝:简单的赋值拷贝
深拷贝:在堆区申请空间,进⾏拷贝操作
浅拷贝带来的问题是堆区内存的重复释放。
解决⽅法是⽤深拷贝,在堆区重新开辟⼀段内存。
#include <iostream>
using namespace std;
class person
{
public:
person(int a,int b)
{
age = a;
height =new int(b);
cout <<"person的有参构造调⽤"<< endl;
}
//深拷贝
person(const person &p)
{
age =p.age;
height =new int(*p.height);
cout <<"person的拷贝构造调⽤"<< endl;
}
~person()
{
if(height !=NULL)
{
delete height;
height=NULL;
}
cout <<"person的析构调⽤"<< endl;
}
int age;
int* height;
};
void test01()
{
person p(18,180);
cout << p.age<<"\t"<<*p.height << endl;
person p2(p);
cout << p2.age<<"\t"<<*p2.height << endl;
}
int main()
{
test01();
return0;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论