day3-C++学习

1.对象的初始化和清理

class Person
{
public:
	//构造函数写法
	//与类名相同,没有返回值,不写void,可以发生重载(可以有参数)
	//构造函数由编译器自动调用,而不是手动调用,而且只会调用一次
	Person()
	{
		cout << "默认无参构造函数" << endl;
	}
	Person(int a)
	{
		cout << "有参构造函数" << endl;
	}

	//析构函数写法
	//与类名相同,类名前面加一个符号,“~”,也没有返回值,不写void,不可以有参数(不能发生重载)
	//析构函数由编译器自动调用,而不是手动调用,而且只会调用一次
	~Person()
	{
		cout << "析构函数" << endl;
	}
};
//如果程序员没有提供构造和析构,系统会默认提供,空实现
Person p1(2);//默认调用了构造和析构,是系统提供的两个空实现的函数

2.构造函数的分类及调用

按照参数进行分类:无参构造函数(默认构造函数) 有参构造函数
按照类型进行分类:普通构造函数 拷贝构造函数

class Person
{
public://构造函数和析构函数必须写在public下才可以调用

	Person()  //默认、无参构造函数
	{
		cout << "默认构造函数的调用" << endl;
	}

	Person(int a)
	{
		cout << "有参构造函数的调用" << endl;
	}

	//拷贝构造函数
	Person(const Person& p)
	{
		mage = p.mage;
		cout << "拷贝构造函数的调用" << endl;
	}

	~Person()  
	{
		cout << "默认析构函数的调用" << endl;
	}

	int mage = 0;
};
void test()
{
	//构造函数调用方式
	//1.括号法调用
	//Person p1(1);//有参
	//p1.mage = 10;
	//Person p2(p1);//拷贝
	//cout << "p2的年龄:" << p2.mage << endl;

	//Person p3;//默认构造函数不要加()Person p3();编译器认为这是函数声明

	//2.显示法调用
	//Person p4 = Person(100);
	//Person p5 = Person(p4);

	//Person(100); //匿名对象,匿名对象的特点:如果编译器发现对象是匿名的,那么在这行代码结束后就释放
	//不能用拷贝构造函数初始化匿名对象
	//Person p6 = Person(p5);//如果写成左值,编译器认为你写成了Person p5,对象的声明;如果写成右值可以

	Person p7 = 100;//相当于调用了 Person p7 = Person(100),隐式类型转换
	Person p8 = p7; //相当于Person p8 = Person(p7)
}

3.拷贝构造函数的调用时机

class Person
{
public:
	Person()
	{
		cout << "默认构造函数的调用" << endl;
	}
	Person(int a)
	{
		cout << "有参构造函数的调用" << endl;
	}

	Person(const Person& p)
	{
		cout << "拷贝构造函数的调用" << endl;
	}

	~Person()
	{
		cout << "析构函数的调用" << endl;
	}

	int age = 0;
};

拷贝调用的时机
1.用已经创建好的对象来初始化新的对象

void test1()
{
	Person p1;
	p1.age = 18;

	Person p2(p1);
}

2.以值传递的方式给函数参数传值

void dowork(Person p1)//Person p1 = Person(p)
{

}

void test2()
{
	Person p;
	p.age = 18;

	dowork(p);
}

3.以值的方式返回局部对象

Person dowork2()
{
	Person p1;
	return p1;
}

void test3()
{
	Person p = dowork2();
}
//Release默认下会做优化

4.构造函数的调用规则

class Myclass
{
public:
	/*Myclass()
	{
		cout << "默认构造函数的调用" << endl;
	}*/
	Myclass(int a)
	{
		cout << "有参构造函数的调用" << endl;
	}
	/*Myclass(const Myclass& c)
	{
		cout << "拷贝构造函数的调用" << endl;
	}*/

	~Myclass()
	{
		cout << "默认析构函数的调用" << endl;
	}
	int m_a = 0;
};

//系统默认给一个类提供3个函数:默认构造函数、拷贝构造函数、析构函数
//1.当我们提供有参的构造函数,那么系统就不会再给我们提供默认构造函数了
//但是系统还会提供默认的拷贝构造函数,进行简单的值拷贝

//2.当我们提供了拷贝构造函数,系统就不会提供其他构造函数了
void test1()
{
	Myclass c1(1);
	c1.m_a = 10;
	Myclass c2(c1);
	cout << c2.m_a << endl;
}

5.深拷贝和浅拷贝

class Person
{
public:
	Person()
	{}
	//构造函数用来初始化属性
	Person(const char* name, int age)
	{
		m_Name = (char*)malloc(strlen(name) + 1);
		if (m_Name != NULL)
		{
			strcpy(m_Name, name);
		}

		m_age = age;
	}
	//拷贝构造,系统会提供默认拷贝构造函数,而且是简单的值拷贝(浅拷贝)
	//自己提供拷贝构造,原因是简单的浅拷贝会释放空间两次,导致崩溃

	//深拷贝
	Person(const Person& p)
	{
		m_age = p.m_age;
		m_Name = (char*)malloc(strlen(p.m_Name) + 1);
		if (m_Name != NULL)
		{
			strcpy(m_Name, p.m_Name);
		}
	}
	~Person()
	{
		cout << "析构函数调用" << endl;
		if (m_Name != NULL)
		{
			free(m_Name);
			m_Name = NULL;
		}
	}
	//姓名
	char* m_Name;
	//年龄
	int m_age = 0;

};

6.初始化列表的基本使用

class Person
{
public:
	/*Person()
	{

	}*/
	//有参构造初始化数据
	/*Person(int a,int b,int c)
	{
		ma = a;
		mb = b;
		mc = c;
	}*/

	//利用初始化列表来初始化数据
	//构造函数后面 + :属性(参数),属性(参数)...
	1.	Person() :ma(10), mb(20), mc(30)
		{}
	2.	Person(int a, int b, int c) :ma(a), mb(b), mc(c)
		{}
	int ma;
	int mb;
	int mc;
};

7.类对象作为成员的案列

class Person
{
public:
	Person()
	{
		cout << "Person的默认构造函数" << endl;
	}
	Person(string name,string phonename,string gamename):mname(name),m_Phone(phonename),m_Game(gamename)
	{
		cout << "Person的有参构造函数" << endl;
		//mname = name;
	}
	void playGame()
	{
		cout << mname << "拿着《" << m_Phone.m_Phonename << "》牌手机,玩着《" << m_Game.m_Gamename << "》游戏" << endl;
	}
	~Person()
	{
		cout << "Person的析构函数" << endl;
	}
	Phone m_Phone;
	string mname;
	Game m_Game;
};
class Phone
{
public:
	Phone()
	{
		cout << "手机的默认构造函数" << endl;
	}
	Phone(string name)
	{
		m_Phonename = name;
		cout << "手机的有参构造函数" << endl;
	}

	~Phone()
	{
		cout << "手机的析构函数" << endl;
	}

	string m_Phonename;
};

class Game
{
public:
	Game()
	{
		cout << "游戏的默认构造函数" << endl;
	}
	Game(string name)
	{
		m_Gamename = name;
		cout << "游戏的有参构造函数" << endl;
	}
	~Game()
	{
		cout << "游戏的析构函数" << endl;
	}

	string m_Gamename;
};
//类对象作为类成员时,构造的顺序先将类对象一一构造,再构造自己,析构与之相反

8.explicit关键字

//作用:防止构造函数中的隐式类型转换
class MyString
{
public:
	MyString(const char* str)
	{}
	explicit MyString(int a)
	{
		mSize = a;
	}
	char* mstr;
	int mSize;
};
void test()
{
	MyString str = "abc";
	MyString str2(10);
	//MyString str3 = 10;//str2字符串为"10",字符串长度为10
	//隐式类型转换  MyString str3 = MyString(10)
	//explicit关键字,防止隐式类型转换
}

9.new运算符使用

class Person
{
public:
	Person()
	{
		cout << "默认构造调用" << endl;
	}
	Person(int a)
	{
		cout << "有参构造调用" << endl;
	}
	~Person()
	{
		cout << "析构函数调用" << endl;
	}
};
void test()
{
	//Person p1;放在栈区开辟
	Person* p2 = new Person;//在堆区开辟
	//所有new出来的对象,都会返回该类型的指针
	//malloc返回void* 还要强转
	//malloc不会调用构造函数
	//new运算符  malloc函数
	//释放堆区空间
	//delete也是运算符,配合new用;malloc配合free用
	delete p2;
}
void test2()
{
	void *p = new Person;
	//当用void*接受new出来的指针,会出现释放的问题
	delete p;
	//无法释放,避免这种写法
}
void test3()
{
	//通过new来开辟数组,一定会调用默认构造函数,所以一定要提供默认构造函数

	Person* pArray = new Person[10];
	//Person pArray[2] = {Person(1),Person(2)};//在栈上开辟数组,可以指定有参构造
	//释放数组
	delete [] pArray;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值