C++基础 03

本文详细介绍了C++中的类构造函数,包括拷贝构造函数的调用场景及其可能导致的问题,构造函数的初始化列表使用,以及如何在构造函数内部管理动态内存。此外,还讨论了静态成员变量和静态成员函数的作用,以及this指针的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.类的构造函数

class Test
{
public:
	//无参构造函数
	Test()
	{
		cout << "无参构造函数" << endl;
	}
	 //有参构造函数
	 Test(int a,int b)
	 {
		 cout << "有参构造函数" << endl;
	 }
	 //赋值或者拷贝构造函数
	 Test(const Test & t)
	 {
		 cout << "赋值或者拷贝构造函数" << endl;
	 }
private:

};

void main()
{	
	Test t;//这里调用了无参构造
	Test t2(1,2);//这里调用有参构造函数
	Test t3=Test(1, 2);
	//这里也调用有参构造函数,相当于先创建一个匿名对象,然后在转成t3;也就是t3对象初始化

	t = t3;//这个调用了t的拷贝构造函数;
	system("pause");
}

初始化尽量放在构造函数中,有些情况就没有机会初始化了;

2.拷贝构造函数的几种调用场景

class Test
{
public:
	int a;
	//无参构造函数
	Test()
	{
		cout << "无参构造函数" << endl;
	}
	 //有参构造函数
	 Test(int a,int b)
	 {
		 cout << "有参构造函数" << endl;
	 }
	 //赋值或者拷贝构造函数
	 Test(const Test & t)
	 {
		 cout << "赋值或者拷贝构造函数" << endl;
	 }
	 ~Test()
	 {
		 cout << "调用了析构函数" << endl;
	 }
	 void setObjiect(Test tt)
	 {
	 }
private:

};

Test getObject()
{
	Test t;
	t.a = 10;
	return  t;//在这里创建了一个匿名对象返回去,使用已有对象创出化匿名对象,调用匿名对象的拷贝构造函数
			//在调用了t的析构函数,把匿名对象返回去,如果发现返回去没有人接受,所以把匿名对象也析构了,调用析构函数;
}

void main(){
	Test t;//这里调用了无参构造
	//Test t2(1,2);//这里调用有参构造函数
	Test t3=Test(1, 2);
	//这里也调用有参构造函数,相当于先创建一个匿名对象,然后在转成t3;也就是t3对象初始化

	//第一种情况:调用了t的拷贝构造函数;用已有对象去初始化一个未有的对象;
	Test t4 = t3;
	//爹二种调用时机;
	Test t5(t3);
	//第三种调用时机,形参调用了拷贝构造函数;实参和形参就是两个不同的对象了
	t5.setObjiect(t3);
	//第四种调用时机,函数返回对象的时候
	Test t6 = getObject();//如果有人接的话,就直接转成t6,不会调用t6的拷贝构造函数;
	cout << "t6a:" << t6.a << endl;

	Test t7;
	t7.a = 100;
	t7 = getObject();//如果用一个已经有的对象去接受的话,匿名对象会被析构掉的;t7已经不是之前的t7了

	cout << "t7.a:" << t6.a << endl;
	system("pause");
}


3.拷贝构造函数引发的“血案”

class Test
{
public:
	int a=5;
	char * name=NULL;
	//无参构造函数
	Test()
	{
		a = 10;
		name =(char*) malloc(24);
		strcpy(name,"abcdefg");
		cout << "无参构造函数" << endl;
	}
	 //有参构造函数
	 Test(int a,int b)
	 {
		 cout << "有参构造函数" << endl;
	 }
	

	 //赋值或者拷贝构造函数
	 Test(const Test & t)
	 {

	 }
	 ~Test()
	 {
		 cout << "调用了析构函数" << endl;
	 }
	 void setObjiect(Test tt)
	 {

	 }
private:
};

void main(){
	
	Test t1;

	//Test t2 = t1;//调用t2的拷贝构造函数,但是t2对象中的成员变量还是类的原始数据;
				//例如:类中的指针指向的是空,在构造函数中给申请了内存,但是在拷贝构造函数中没有申请内存,当你调用拷贝构造的时候那个指针还是NULL;
				//就相当于对象重新创建只不过调用的是拷贝构造函数
	Test t2;
	t2 = t1;//这种操作字面上就是赋值,不会调用任何构造函数,变量的值都是相同的,从t1复制到t2,但是变量的内存地址是不同的;
			//对于指针的话就是指针本身的地址是不同的,但是指针指向的内存空间的地址是相同的。这里就存在内存释放的时候会重复释放的问题。
			//如果t1和t2都给指针分配了内存,当执行t2=t1的时候,t2中之前分配的内存就泄露了;
			//这里需要重载=操作符;

	cout << t1.a<<"----"<< t2.a << endl;
	printf("指针的地址%d    %d\n", &(t1.name), &(t2.name));
	printf("a的地址%d    %d\n", &(t1.a), &(t2.a));
	cout << t1.name << "----" << t2.name << endl;

	system("pause");
}

4.构造函数的初始化列表

class Teacher
{
public:
	Teacher(int m,int n)
	{
		cout << "Teacher有参构造函数" << endl;
	}
	~Teacher()
	{
		cout << "Teacher调用了析构函数" << endl;
	}

private:
};
class Test
{
public:
	int a;
	int b;
	Teacher t1;
	Teacher t2;
	const int c;
	//无参构造函数
	Test():t1(1,2),t2(1,2),c(5)
	{
		cout << "Test无参构造函数" << endl;
	}
	 //有参构造函数
	 Test(int a,int b) :t1(1, 2), t2(1, 2), c(5)
	 {
		 cout << "Test有参构造函数" << endl;
	 }
	 //有参构造函数
	 Test(int a, int b,int m,int n) :t1(m, n), t2(m, n), c(5)
	 {
		 cout << "Test有参构造函数" << endl;
	 }
	 //赋值或者拷贝构造函数
	 Test(const Test & t) :t1(1, 2), t2(1, 2), c(5)
	 {

	 }
	 ~Test()
	 {
		 cout << "Test调用了析构函数" << endl;
	 }
	 
private:
};

void main(){
	//因为在Test类中存在,别的类的变量,所以在初始化Test的时候也要初始化别的类.
	//初始化内部变量对象,必须通过外部对象的构造函数初始化,语法:Test():t1(1,2),t2(1,2)  外部构造方法:内部构造方法
	//构造函数的执行顺序,先执行被走合函数的构造函数
	//类种如果有const修饰的变量,也必须在构造函数的后面:初始化;
	Test t;
	Test t2(1,2,2,3);
	system("pause");
}


构造函数的执行顺序:
先初始化的后析构,后初始化的先析构


5.在构造函数中再次调用构造函数的话,会会产生一个匿名对象,就是两个对象了,但是匿名对象在被调用的构造函数结束的时候会被析构掉;


6.C++中动态分配和释放内存,new和delete关键字:

class Teacher
{
public:
	Teacher()
	{
		cout << "构造方法" << endl;
	}
	Teacher(int a)
	{
		cout << "有参构造方法" << endl;
	}
	~Teacher()
	{
		cout << "析构方法" << endl;
	}
};


//new 和delete是C++的关键字
//new 基础变量类型	分配数组变量	分配类对象
void main(){

	//在c语言中 
	int * p=(int *)malloc(sizeof(int));
	*p = 100;
	free(p);//delete(p); 这两种释放都是可以的

	//在C++中
	int* p1 = new int;//分配内存不初始话的;
	*p1 = 100;
	delete(p1);//free(p1); 这两种释放都是可以的

	int* p2 = new int(100);//分配内存和初始话;
	delete(p2);//free(p2); 这两种释放都是可以的

	//在c语言中分配数组
	int * arr = (int *)malloc(sizeof(int) * 10);
	arr[0] = 100;
	free(arr);//delete[] arr;这两种释放都是可以的

	//在C++中分配数组
	int* array = new int[10];
	array[1] = 100;
	delete(array);//free[] array;这两种释放都是可以的

	//在c中,在分配内存中不会调用对象构造和析构方法
	Teacher* t = (Teacher*)malloc(sizeof(Teacher));
	free(t);//delete(t);释放内存了,但是会调用析构方法;

	//在C++中 
	Teacher* t2 = new Teacher(10);//调用构造方法
	delete t2;//调用析构函数;
	//free(t2);//这样也释放内存了,但是不会调用析构函数的;
	//总结,在使用new和delete的时候还是成对的去使用;malloc和free是成对的使用
	system("pause");
}


7.静态成员变量和静态成员函数

静态是是属于类的,对象共用的;基本用法和java的静态是一样的,在C++中 通过类名调用有点区别:类名::静态成员或者方法

8.this指针

class Teacher
{
public:
	int a;
	Teacher(int a)//==>在c++编译器底层是这样做的Teacher(Teacher * this,int a)
	{
		this->a = a;
	}
};


void main(){
	Teacher t(5);//这边调用是t(&t,5);对象取地址传给方法的;
	//这就是类的存放代码区,对象存在很多个的时候,调用同一份方法的时候会传对象过去的;也就是我们认为的找到对象自己的函数;
	
	system("pause");
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值