C++中对象的初始化和清理

发布于:2024-12-06 ⋅ 阅读:(108) ⋅ 点赞:(0)

一、.初始化:

对象的初始化使用构造函数

构造函数

构造函数:主要作用在于创造对时为对象的成员属性(成员变量)赋值,构造函数由编译器自动调用,无需手动调用

语法:类名(){}

1.构造函数没有返回值,函数名前也不用写void

2.函数名与类名相同

3.构造函数可以有参数,因此可以发生重载

4.程序在调用对象的时候会自动调用构造函数,无需手动调用,而且只会调用一次

5.当已经提供了有参构造时,程序不会提供无参构造(若此时调用无参构造,程序报错,须程序员手动提供无参构造)

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
class A {
	int* p;
public:
	A()//构造函数,函数名与类名相同,没有返回值,函数名前不用写void,
		//如果没有实现构造函数编译器会提供默认的构造函数
	{
		cout << "默认构造" << endl;
	}
	A(int n) {
		if (n != 0) {
			p = new int[n];
			cout << "使用构造函数在堆区申请了n个int类型的变量" << endl;
 }
	}
};
int main() {
	A p;//输出:默认构造。在创建对象时编译器会帮我们自动调用构造函数,无需手动调用
	A p1(2);//输出:使用构造函数在堆区申请了n个int类型的变量。调用有参构造创造对象
	A p2();//输出:  编译器会把它认为是函数声明,A是返回值类型,p2是函数名,()是函数参数
	return 0;
}

构造函数的分类及调用:

分类:

1.按照参数分:有参构造和无参构造

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

调用方式:

1.括号发

2.显示法

3.隐式转换法

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
class A {
	int* p;
public:
	A()
	{
		cout << "默认构造" << endl;
	}
	A(int n) {
 cout << "调用有参构造" << endl;
	if (n > 0)p = new int(n);//p指向一块int类型的内存,值为n
	else{
	p = NULL;
	cout << "数据不准确" << endl;
 }
	}
	void a(){
	 if (p) {
		cout << "打印p指向堆区内存值:" << *p << endl;
	 }
}
};
int main() {
	A t(1);//输出:调用有参构造。括号法相当于A t=A(1);
	A t1 = A(3);//输出:调用有参构造。显示法
	A t2 = 3;//输出:调用有参构造。隐式转换法,在此处会调用参数为int类型的构造函数,将3转换为A类型对象
	A t3();//不是括号发,编译器会把它认为是函数声明,A是返回值类型.t3是函数名,()是函数参数
	A t4;//输出:默认构造。调用无参构造
	return 0;
}

构造函数的调用规则

在默认情况下,C++至少会给一个类添加3个函数:

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

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

3.默认拷贝构造函数,对属性进行值拷贝。(简单的赋值)

构造函数调用规则:

1.如果用户定义有参构造,C++不再提供默认的无参构造,但会提供默认的拷贝构造

2.如果用户定义了拷贝构造,C++不再提供其他的任何构造函数(无参、有参、默认拷贝构造)

#include<iostream>
#include<vector>
using namespace std;
class Person {
	
public:
	int n;
	Person() {
		cout << "无参构造" << endl;
	}
	Person(int n) {
		this->n = n;
		cout << " 有参构造" << endl;
	}
	Person(const Person& other) {
		this->n = other.n;
		cout << " 拷贝构造" << endl;
	}
	~Person() {
		cout << "析构函数" << endl;
	}
};
void test1() {
	Person p1(18);
	
	Person p2(p1);//如果不写拷贝构造,编译器会自动添加默认的拷贝构造(浅拷贝)
	//此处的拷贝构造,相当于使用一个已经创建完毕的对象(已经存在的对象)初始化一个新对象
	cout << "p2为:" << p2.n << endl;
}
void test2() {
	//如果用户提供有参构造,编译器不会提供默认的无参构造,但会提供默认的拷贝构造
	Person p1;//此时如果用户没有提供默认构造,编译器会报错
	Person p2(10);//调用用户提供的有参构造
	Person p3(p2);//调用拷贝构造,如果此时用户没有提供拷贝构造,编译器会提供默认的拷贝构造
	
	//如果用户提供了拷贝构造,编译器不会提供其他任何的拷贝构造
	Person p4;//此时如果用户没有提供默认构造,编译器会报错
	Person p5(10);//调用用户提供的有参构造,此时如果用户没有提供有参构造,编译器会报错
	Person p6(p5);//调用拷贝构造
}
int main() {
	test1();
	return 0;
}

二、对象的清理

对象需要调用析构函数来清理

析构函数

主要作用在于对象销毁前系统自动调用,执行一些清理工作

语法:~( )类名{ }

1.析构函数没有返回值,也不用写void

2.函数名跟类名相同,在名称前加符号:~

3.析构函数不可以有参数,因此不能发生重载

4.程序在对象销毁前会自动调用析构,无需手动调用,而且只会调用一次

#include<iostream>
using namespace std;
class Pointer {
	int* p=NULL;
public:
	Pointer() {
		cout << "默认构造" << endl;
	}
	Pointer(int n) {
		cout << "调用有参构造" << endl;
		if (n > 0) {
			p = new int[n];//使用构造函数在堆区申请了n个int类型的变量
		}
	}
	//析构函数用于帮助我们释放指针变量指向的堆区内存
	~Pointer() {
		if (p)delete[]p;
	}
};
void test() {
	Pointer p(2);
}
int main() {
	test();
	return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到