700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > C++学习笔记【类和对象】【构造函数和析构函数】

C++学习笔记【类和对象】【构造函数和析构函数】

时间:2023-05-19 00:29:45

相关推荐

C++学习笔记【类和对象】【构造函数和析构函数】

主要内容来源:/video/BV1et411b73Z?spm_id_from=333.999.0.0

一、构造函数

构造函数的分类

1.按参数分:无参构造(默认)、有参构造

即构造函数有无参数

由于构造函数可以带有参数,因此构造函数也可以函数重载

#include<iostream>#include<String>using namespace std;class Person{public://构造函数Person() {cout<<"调用Person的无参构造函数"<<endl; }Person():age(10) {cout<<"调用Person的无参构造函数"<<endl; } 后加冒号可给对象成员赋初值Person(int a) {cout<<"调用Person的有参构造函数"<<endl;}Person(int a,int b) {cout<<"调用Person的有参构造函数"<<endl;}private:int age;}int main(){Person p;p.Person(1,1);//将调用Person(int a,int b) }

2.按类型分:普通构造、拷贝构造

class Person{public://构造函数Person() {cout<<"调用Person的无参构造函数"<<endl; }Person(int a) {cout<<"调用Person的有参构造函数"<<endl;}//拷贝构造函数Person(const Person &p) //固定格式,将传入的对象p的所有属性,拷贝到我身上。{age = p.age;}private:int age;}

构造函数的调用方式

1.括号法

#include<iostream>#include<String>using namespace std;class Person{public://构造函数Person() {cout<<"调用Person的无参构造函数"<<endl; }Person(int a) {cout<<"调用Person的有参构造函数"<<endl;}Person(const Person &p) {age = p.age;}private:int age;}//********************构造函数调用**************************************//void func(){Person p1;//默认构造函数调用,即创建对象时会默认调用Person p2(10);//创建对象时调用有参构造函数Person p3(p2);//创建对象时调用拷贝构造函数,将已创建的对象p2拷贝。}int main(){func();return 0;}

注意事项

调用默认构造函数的时候,不要加括号。

如Person p;不能写成 Person p();

编译器会把 Person p()当成一个函数声明(返回值类型为Person,函数名为p)

2.显示法

.......void func(){Person p1;//用显示法调用默认构造函数Person p2 = Person(10);//用显示法调用有参构造函数Person p3 = Person(p2);//用显示法调用拷贝构造函数//*************注意************//Person(10);//此为匿名对象,当前行执行完毕后,系统会立即回收掉匿名对象。//因为没有名称,后续也无法调用此对象,所以其没有意义,故要被系统回收。}

注意事项

不要利用拷贝构造函数初始化匿名对象

如 Person(p2);编译器会认为Person(p2)等价于Person p3,造成重命名的错误

3.隐式转换法

void func(){Person p2 = 10;//用隐式转换法调用有参构造函数。相当于 Person p2 = Person(10);Person p3 = p2;//用隐式转换法调用拷贝构造函数。相当于 Person p3 = Person(p2);}

二、构造函数调用规则

只要自己定义了拷贝构造函数,就必须也要定义构造函数。

三、浅拷贝与深拷贝

#include...class Person{Person(int m_age,int m_height) {age = m_age,height = new int(m_height); }//调用有参构造,其中m_height在堆区开辟,需要手动删除~Person(){if(height != NULL){delete height; height = NULL;}}//调用析构函数,删除堆区的数据int age;int * height;}int main(){Person p1(18,180);Person p2(p1);//浅拷贝return 0;}

上述代码无法运行

浅拷贝是简单的赋值操作,会将p1的age,height直接拷贝给p2,age没有问题,但height是指针,这样p1和p2中的height都会指向堆区中的180,这样在执行析构函数时,会执行两遍delete height命令,这是违规操作。原因就是默认的拷贝构造函数是浅拷贝,只是进行简单的赋值操作。

此时需要自己编写拷贝构造函数,进行深拷贝。

#include...class Person{Person(int m_age,int m_height) {age = m_age,height = new int(m_height); }//调用有参构造,其中m_height在堆区开辟,需要手动删除Person(const Person & p){age = p.age;height = new int (*p.height);//在堆区重新开辟一个空间,存储自己的值。}//调用拷贝构造函数,进行深拷贝。~Person(){if(height != NULL){delete height; height = NULL;}}//调用析构函数,删除堆区的数据int age;int * height;}int main(){Person p1(18,180);Person p2(p1);//浅拷贝return 0;}

总结

如果对象属性有在堆区开辟的,一定要自己提供拷贝构造函数,以防浅拷贝带来的问题。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。