C++构造函数析构函数 拷贝04

类中限定对象的长相

C++构造函数

为什么需要构造函数?
  • 构造函数:可以说你所创建对象的骨骼,你的构造函数决定了你可以创建什么样的对象。
  • 构造函数更多是用来初始化数据成员
  • 不写构造函数:只能创建 不带参数的对象
  • 当我们自己写了构造函数,默认的构造函数就不存在了
class Boy {
public:
	void print() {
		cout << "Im a boy class`s objection" << endl;
	}
protected:
	string name;
	int age;
};
	Boy boy;
	boy.print();
	Boy bboy = { "boy",19 };// 错!!!

构造函数长什么样子

#include"iostream"
#include"string"
using namespace std;
class MM {
public:
	MM(){};//  默认构造函数
	MM(string nname , int aage) {
		name = nname;
		age = aage;
		cout << "Im consttructorfun" << endl;
	}
	void print()
	{
		cout << name << '\t' << age << endl;
	}
protected:
private:
	string name;
	int age;
};
int main()
{
	MM mm;//调用默认构造函数
	MM girl("Lisa", 18);// 调用自己写构造函数
	while(1);
	return 0;
}

在这里插入图片描述

初始化参数列表 : 只有构造函数有<这个必须学会,继承 会用到>

好处:避免形参名和数据成员名相同的导致问题

	MM(string nname="", int aage = 18) :name(nname), age(aage) {
		name = nname;
		age = aage;
		cout << "Im consttructorfun" << endl;
	}
构造函数缺省 (MM(string nname="", int aage = 18) :name(nname), age(aage))可以让我们写出 已知参数不完整对象
  • 人话:这种写法可以设置默认参数
#include"iostream"
#include"string"
using namespace std;
class Boy {
public:
	void print() {
		cout << "Im a boy class`s objection" << endl;
	}
protected:
	string name;
	int age;
};
class MM {
public:
	//MM() {};//  默认构造函数
	MM(string nname="", int aage=88 /*默认参数*/) :name(nname), age(aage) {
		name = nname;
		age = aage;
		cout << "Im consttructorfun" << endl;
	}
	void print()
	{
		cout<< name << '\t' << age << endl;
	}
protected:
private:
	string name;
	int age;
};
int main()
{
	Boy boy;
	boy.print();
	// bboy = { "boy",19 };wrong
	MM mm;//调用默认构造函数
	mm.print();
	MM girl("Lisa", 18);// 调用自己写构造函数
	girl.print();
	MM mmy = {"KK"}; // 年龄默认88
	mmy.print();
	while(1);
	return 0;
}

运行结果:
在这里插入图片描述

析构函数

  • 析构函数长什么样子?
    • 无返回值
    • 无参数
    • 函数名: ~类名
    • 不写的话会存在默认的析构函数
    • 析构函数不需要自己 调用,对象死亡的之前会调用析构函数
	~MM();//析构函数
  • 为什么需要析构函数(什么时候需要自己手动写析构函数)

    • 当类中的数据成员是指针,并且动态申请内存就需要手写析构
    • 析构函数用来释放数据成员申请动态内存
#include"iostream"
#include"string"
using namespace std;
class MM {
public:
	MM(string nname = "", int aage = 18) :name(nname), age(aage) {
		int *p = new int;
		name = nname; age = aage;
	}
	void print() {
		cout << name << '\t' << age  << endl;
		cout << num << endl;
	}
	~MM() {
		cout << "我是析构函数" << endl;
	}//析构函数
protected:
private:
	string name;
	int age;
	int *num;
};
int main()
{
	MM m;
	m.print();
	m.~MM();// 手动调用
	//  我的为什么不自己调用?
	MM mm = { "kk" };
	mm.print();
	while (1);
	return 0;
}

在这里插入图片描述

拷贝构造函数

  • 什么时候调用拷贝构造?

    • 当通过一个对象去创建出来另一个新的对象时候需要调用拷贝
  • 拷贝构造函数也是构造函数,长相和构造函数一样的,只是参数是固定

    • 拷贝构造函数唯一的参数是对对象引用
  • 不写拷贝构造函数,也存在一个默认的拷贝构造函数

  • 拷贝构造函数作用: 通过一个对象去初始化另一个对象
    <会继承上一个对象的参数>
    如: MM girl = mm;
    girl.print();

在这里插入图片描述

#include"iostream"
#include"string"
using namespace std;
class MM {
public:
	MM(string nname = "", int aage = 18) :name(nname), age(aage) {
		int *p = new int;
		name = nname; age = aage;
	}
	void print() {
		cout << name << '\t' << age  << endl;
		cout << num << endl;
	}
	MM(MM& mm)
	{
		name = mm.name;
		age = mm.age;
		cout << "我是拷贝构造函数" << endl;
	}
	~MM() {
		cout << "我是析构函数" << endl;
	}//析构函数
protected:
private:
	string name;
	int age;
	int *num;
};
int main()
{
	MM m;
	m.print();
	m.~MM();// 手动调用
	//  我的为什么不自己调用?
	MM mm = { "kk" };
	mm.print();
	MM girl = mm;
	girl.print();
	girl = { "girl",19 };
	girl.print();
	while (1);
	return 0;
}
	//显示调用调用
	MM girl(mm);        //通过一个对象创建另一个对象
	girl.print();
	//隐式调用
	MM girl2 = mm;		//拷贝构造
	girl2.print();

深浅拷贝

  • 浅拷贝: 默认的拷贝构造叫做浅拷贝

  • 深拷贝: 拷贝构造函数中做了new内存操作,并且做拷贝赋值的操作

#include"iostream"
#include"string"
using namespace std;
class MM {
public:
    //MM() = default;// 想要保留默认够赞函数 并写出不带参 对象
	MM(const char* nname="gg",int aage=18) :age(age) {// 用缺省写法时   上面代码 可以省略
		age = aage;
		name = new char[strlen(nname) + 1];
		strcpy_s(name, strlen(nname) + 1, nname);
		cout << "Im construction fun" << endl;
	}
	MM(int aage) :name(name) {
	//   为什么写不出
		age = aage;
		cout << "Im construction fun2" << endl;
	}
	~MM() {
		cout << "我是死神析构函数" << endl;
		delete name;
	}
	void print()
	{
		cout << name << '\t' <<age << endl;
	}
protected:
private:
	char* name;
    int age;
};
int main()
{
	MM mm;
	mm.print();//默认名 gg 默认年龄18
	MM girl = {"JJ"};
	girl.print();//默认年龄 18
	MM boy("HH", 19);
	boy.print();
	return 0;
}

在这里插入图片描述

  • 为什么做不到 名字 默认 年龄已知?
  • 拷贝构造什么时候需要加const修饰参数?
    • 当存在匿名对象赋值操作的时候,必须要const修饰
      匿名对象 临时变量 《这时需要 构造中写 const MM mm》

构造和析构顺序问题

  • 普通对象,构造顺序和析构顺序是相反
  • new出来的对象,delete会直接调用析构函数
  • static对象,当程序关闭的时候,生命周期才结束,所以是最后释放

*******<我自己的析构函数 调用的有问题,暂时贴老师代码了>
(;´д`)ゞ (;д;)

#include <iostream>
#include <string>
using namespace std;
class MM
{
public:
	MM(string name = "x") :name(name) {
		cout << name;
	}
	~MM() {
		cout << name;
	}
protected:
	string name;
};
int main()
{
	{
		MM mm1("A");			//A
		static MM mm2("B");		//B   程序关闭时候才死亡,最后析构
		MM* p3 = new MM("C");	//C
		MM mm4[4];				//xxxx
		delete p3;				//C  delete 直接调用析构
		p3 = nullptr;
		//xxxxAB
	}
	//ABCxxxxCxxxxAB
	return 0;
}

在这里插入图片描述
Homework:
在这里插入图片描述
这个问题我一直没解决掉!!!!!!!!!!

#include"iostream"
#include"cstring"
using namespace std;
class 	myString {
public:
	myString() {};//等效 myString()=default;
	myString(const char* Str ) {//传常量用
		str = new char[strlen(str)+1];
		strcpy_s(str, strlen(str) + 1, Str);
	}
	// 因为有 指针申请,所以一定是深拷贝
	myString(const myString& object)
	{
		str = new char[strlen(object.str) + 1];
		strcpy_s(str, strlen(object.str) + 1, object.str);
	}
	char* c_str() {
		return str;
	}
	char* data(){
		return str;
	}
	myString append(const myString& object) {
		myString temp;
		int lon = 2 * strlen(temp.str);
		strcat_s(temp.str,lon, str);
		strcat_s(temp.str, lon, object.str);
		return temp;
	}
	int compare(myString& object)//   0  1  -1
	{
		return strcmp(object.str, str);
	}
	~myString() {
		delete str;
		str = nullptr;
		cout << "析构函数1" << endl;
	}
private:
protected:
	char* str;
};
int main() {
	//1.实现string中创建方式
	myString str1;// 需要无惨构造函数
	myString str2("ILoveyou");
	myString str3(str1);
	myString str4 = str2;
	//2.通过实现data和c_str函数 打印字符串
	cout << str2.c_str() << endl;  //打印ILoveyou
	cout << str2.data() << endl;   //打印ILoveyou
//3.实现append 实现字符串的链接
	myString strOne = "one";
	myString strTwo = "two";
	myString strThree = strOne.append(strTwo);
	cout << strThree.data() << endl;	    //onetwo
//4.实现字符串比较
	cout << strOne.compare(strOne) << endl;	//0
//5.手写析构函数释放内存

	return 0;
}

总结

总结:

  • C++中结构体中 用了构造函数就是 class
  • C++ 中
    结构体 默认public
    class 中默认private
  • 对构造缺省不够了,急需加深理解,理清思路
  • 析构调用 有问题,也许编译器没调好

浅拷贝:通过对象创建对象存在 西沟问题(多次释放)
深拷贝: 在 默认拷贝中 申请内存strcpy(name,name…)存放 避免了多次释放

<< 这次作业写得非常艰难《昨天晚上2+今天上午》,博客也是。因为拿课余时间写加上 思路不清晰花了大量时间效果也不佳!
应该要做出改变。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值