c++基础--对象初始化和清理(构造函数与析构函数)

构造函数与析构函数

完成对象的初始化与清理

1.构造函数

/*
*构造函数的分类及调用
* 按照参数分类  无参构造(默认) 和有参构造
* 按照类型分类  普通构造和拷贝构造
*/
class person {
public:
	int age;
	string name;
    //无参构造
	person() {
		cout << "构造函数调用" << endl;
	}
    //有参构造
	person(int a) {
		age = a;
		cout << "有参构造" << endl;

	}
	//拷贝构造函数
	person(const person& p) {
		cout << "拷贝构造" << endl;
		age = p.age;
	}
    //析构函数
	~person()
	{
		cout << "析构函数调用" << endl;
	}
};
//构造函数调用(1.括号法 2.显示法 3.隐式转换)
//1.括号法
void test1(){
    person p1;    //默认构造函数调用
    person p2(20);//有参构造
    person p3(p2);//拷贝构造函数调用
//注意事项:默认参数不要加括号。例如person p1() 编译器会认为是一个函数声明
    cout<<"年龄是:"<<p2.age<<endl;
    cout<<"年龄是:"<<p3.age<<endl;
}
//2.显示法
void test2(){
    person p2=person(10);
    person p3=person(p2);
}
//person (10) 匿名对象
//注意事项 不要利用拷贝构造函数初始化一个匿名对象
//person (p3)=person p3 重定义
//3.隐式转换
void test3(){
    person p1=10;//person p1=person (10)
    person p2=p1;//person p2=person (p1) 
}

2.拷贝构造函数调用时机

class person
{
public:
	person() {
		cout << "构造函数调用" << endl;
	}
	person(int a) {
		age = a;
		cout << "有参构造" << endl;
	}
	person(const person &p)
	{
		age = p.age;
		cout << "拷贝函数调用" << endl;
	}
	~person() {
		cout << "析构函数调用" << endl;
	}
	int age;
};
//1.使用一个已经创建完毕的对象来初始化一个新对象
void test1() {
	person p1(20);
	person p2(p1);
    person p3=p1;
	cout << p2.age << endl;
};
//2.值传递的方式给函数传值
void dow(person p) {
	
}
void test2() {
	person p3;
	dow(p3);
}
//3.值方式返回局部对象
person dow2() {
	person p4;
	cout << (int*)&p4 << endl;
	return p4;
}
void test3() {
	person p = dow2();
	cout << (int*)&p << endl;
}

3.构造函数调用

调用规则

  1. 默认情况下,c++编译器给一个类至少提供三个函数:

    默认构造参数(无参,函数体为空)

    默认析构函数(无参,函数体为空)

    拷贝构造函数

  2. 提供有参构造函数之后,不再提供默认构造函数,依然提供拷贝构造函数。

  3. 提供拷贝构造函数后,其他的不提供。

class person{
public:
    person(){
		cout<<"默认构造函数调用"<<endl;
    }
    person(int age){
        m_age=age;
        cout<<"有参构造函数调用"<<endl;
    }
    person(const person &p){
        m_age=p.m_age;
        cout<<"拷贝构造函数调用"<<endl;
    }
    ~person(){
		cout<<"析构函数调用"<<endl;
    }
    int m_age;
}
void test01(){
	person p;//只提供有参构造后,错误
}
int main(){

	system("pasue");
    return 0;
}

4.深拷贝和浅拷贝

浅拷贝:简单的赋值拷贝操作 浅拷贝堆区内存重复释放非法操作
深拷贝:在堆区重新申请空间,进行拷贝操作

class person {
public:
   person() {
   	cout << "构造函数调用" << endl;
   }
   person(int age,int height) {
   	cout << "有参构造函数调用" << endl;
   	m_age = age;
   	m_height = new int(height);
   	//new开辟的是堆区 需要用指针接受
   }
   //深拷贝
   person(const person& p) {
   	cout << "拷贝构造函数调用" << endl;
   	m_age = p.m_age;
   	//m_height = p.m_height;编译器默认实现
   	m_height = new int(*p.m_height);
   }
   ~person() {
   	//析构代码 将堆区开辟数据做释放操作
   	if (m_height != NULL) {
   		delete m_height;
   		m_height = NULL;
   	}
   	cout << "析构函数调用" << endl;
   }
   int m_age;
   int* m_height;
};
void test01() {
   person p1(18,20);
   cout << "p1的年龄:" <<p1.m_age<<"身高:"<<*p1.m_height << endl;
   person p2(p1);
   cout << "p2的年龄是:" << p2.m_age <<"身高:"<<*p2.m_height << endl;
}

5.初始化列表

初始化列表和构造函数都是实现对象初始化

class person {
public:
	//传统初始化方式
	person(int a,int b,int c) {
		m_a = a;
		m_b = b;
		m_c = c;
	}
	//初始化列表
	person(int a, int b, int c) :m_a (a), m_b (b), m_c (c){}
	void print() {
		cout << m_a << endl;
	}
	int m_a;
	int m_b;
	int m_c;
};

6.类对象作为成员

先构造其他类,再构造自己

class phone {
public:
	phone(string name) {
		p_name = name;
		cout << "phone的构造函数调用" << endl;
	}
	~phone() {
		cout << "phone的析构函数" << endl;
	}
	string p_name;
};
class person {
public:
	//初始化列表
	person(string name, string p_name) :m_name(name),p_name(p_name)
	{
		cout << "person的构造函数调用" << endl;
	}
	~person() {
		cout << "person的析构函数" << endl;
	}
	string m_name;
	phone p_name;

};
//当其他类的对象作为本类的成员,先构造其他类对象,再构造自身
//析构函数与构造函数相反
void test() {
	person p("张三","华为");
	cout << p.m_name << p.p_name.p_name<< endl;

}

7.静态成员函数

//静态成员函数
//所有对象共享一个函数
//静态成员函数只能访问静态成员变量
class person {
public:
	static void fun() {
		m_a = 100;
		//m_b = 10;不可访问非静态变量
		cout << m_a << endl;
	}
	//静态成员变量
	static int m_a;//声明但是未定义
	int m_b;
private://静态成员函数也有访问权限
	int m_c;
};
//类外显示定义,不需要写static
int person::m_a = 10;//定义同时初始化
posted @ 2021-07-16 08:14  pleasurea  阅读(120)  评论(0)    收藏  举报