入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

C++之赋值函数和析构函数

创建时间:2016-11-06 投稿人: 浏览次数:474


析构函数

自动调用-------跟 构造函数相近


析构函数 
特点1:对象消失的时候自动调用
特点2:函数名----类名 相同;前边加~
特点3:系统有默认的析构函数(但它什么都不干)-------当有成员变量是动态内存分配时,就必须重写析构函数
特点4:函数原型永远就1个



//代码:
//main.cpp


#include <iostream>
#include <iomanip>
#include <string.h>
#include <stdlib.h>
#include "Student.h"
using namespace std;


int main()
{
	CStudent stu1(1001,"zhangsan");
	//stu1.free_name();				//如果没有析构函数,我


们就必须自己定义1个函数,来释放name;并手动来执行。----用了析构只是方便了


	return 0;
}




//Student.cpp中完善 析构函数
CStudent::~CStudent()
{
	free(name);
	cout<<"析构函数运行了"<<endl;
}




如果使用new来建立 对象,就必须使用delete来释放对象------此时析构函数才会被调用


如果使用new来建立 对象,就必须使用delete来释放对象------否则,析构函数不会被调

//用代码:
int main()
{
	//CStudent stu1(1001,"zhangsan");
	//stu1.free_name();


	CStudent *pstu=new CStudent(1001,"zhangsan");
	delete pstu;


	return 0;
}


赋值函数

特点1:系统有默认的 赋值函数------一般不能用(因为简单的赋值语句,在使用char * name时,会是浅复制)
特点2:所以一般要重写
特点3:------不是构造函数(定义变量时调用)


//代码:
//main.cpp
int main()
{
	CStudent stu1(1001,"zhangsan");
	CStudent stu2(1002,"lisi");
	stu2=stu1;//stu2.fun(stu1);		//二者几乎等价,所以,我们先来


//定义1个成员函数 fun,实现nummber和name的复制
	stu2.print_student();


	return 0;
}



赋值函数的书写步骤:
先写fun函数,验证通过后-------将fun替换为operator=----------------main


函数中,直接改为stu2=stu1;


//main.cpp
int main()
{
	CStudent stu1(1009,"zhangsan");
	CStudent stu2(1002,"lisi");
	//stu2=stu1;//stu2.fun(stu1);		//二者几乎等价,所以,我们先来


//定义1个成员函数 fun,实现nummber和name的复制
	//stu2.operator=(stu1);//fun-----   operator=
	stu2=stu1;
	stu2.print_student();
	return 0;
}


//Student.h
	void operator=(CStudent &stu1);
	
//Student.cpp
void CStudent::operator=(CStudent &stu1)
{
	number=stu1.number;
	//name=stu1.name;
	name=(char *)malloc(strlen(stu1.name)+1);
	strcpy(name,stu1.name);
	return;
}

	
//进一步完善 赋值函数:
//原因:自己给自己赋值    -----应直接返回;否则,程序会崩溃
//main.cpp
int main()
{
	CStudent stu1(1009,"zhangsan");
	CStudent stu2(1002,"lisi");
	//stu2=stu1;//stu2.fun(stu1);		//二者几乎等价,所以,我们先来


定义1个成员函数 fun,实现nummber和name的复制
	//stu2.operator=(stu1);//fun-----   operator=
	//stu2=stu1;
	stu2=stu2;				//自己给自己赋值----可能会有问


题
	stu2.print_student();
	return 0;
}


void CStudent::operator=(CStudent &stu1)
{
	if(&stu1==this)
	{
		return;
	}
	number=stu1.number;
	//name=stu1.name;
	name=(char *)malloc(strlen(stu1.name)+1);
	strcpy(name,stu1.name);
	return;
}


//进一步完善 赋值函数:
//原因:链式传送的需求,所以要有返回值


//main.cpp
int main()
{
	CStudent stu1(1009,"zhangsan");
	CStudent stu2(1002,"lisi");
	CStudent stu3(1003,"wangwu");
	stu3=stu2=stu1;
	stu1.print_student();
	stu2.print_student();
	stu3.print_student();
	return 0;
}




//Student.cpp
CStudent &CStudent::operator=(CStudent &stu1)
{
	if(&stu1==this)
	{
		return *this;
	}
	number=stu1.number;
	//name=stu1.name;
	name=(char *)malloc(strlen(stu1.name)+1);
	strcpy(name,stu1.name);
	return *this;
}



//给name赋值的代码解析:
//代码1:
int main()
{
	char *name=new char[10];
	name="abcd";
	cout<<name;
	return 0;
}
//注意:10个内存空间根本没有使用;而且存它的首地址的变量name,被修改后,这10个内


//存空间也永远不会被delete掉,发生了内存泄露
//但输出结果 正常


代码2:
int main()
{
	char *name=new char[10];
	//name="abcd";
	strcpy(name,"abcd");
	cout<<name;
	return 0;
}
//注意:是深复制。将另外1个字符串"abcd",复制了1份,存到了10个字节的内存空间中(当然只占了前5个字节的空间)
//输出结果   也正常


name    ----382c90
        ----43201c   name被改成 该地址


	




int main()
{
	//char name[10]="abcd";  这行语句等价于下面的语句。  =不是纯粹的赋值   


 ----因为它在定义变量


	char name[10];
	name[0]="a";    //=是纯粹的赋值,要求2边数据类型要一致--------因为前面


没有 数据类型,说明不是在定义变量
	name[1]="b";
	return 0;
}


////////////////////////////////////////////////////////////
int main()
{
	//char name[10]="abcd";
	char *name=new char[10];
	strcpy(name,"abcd");


	char *name2=name;   //这种用法很危险,如下
	delete name;		//释放name,也相等于 同时释放name2----因为大家指向了同一内存空间

	delete name2;


	return 0;
}



//进一步完善赋值函数-------name被重新赋值了(使用malloc),而以前name里有"lisi",结果以后再也释放不了了

CStudent &CStudent::fun(CStudent &stu1)
{
	if(&stu1==this)
	{
		return *this;
	}
	number=stu1.number;
	//name=stu1.name;
	free(name);
	name=(char *)malloc(strlen(stu1.name)+1);
	strcpy(name,stu1.name);
	return *this;
}


//赋值函数再改进--------考虑到malloc可能会分配失败。
CStudent &CStudent::fun(CStudent &stu1)
{
	if(&stu1==this)
	{
		return *this;
	}
	number=stu1.number;
	//name=stu1.name;
	//free(name);
	char *name_bak=name;
	name_bak=(char *)malloc(strlen(stu1.name)+1);
	if(name_bak==NULL)
	{
		return *this;
	}
	free(name);
	name=name_bak;
	strcpy(name,stu1.name);
	return *this;
}





1、自定义1个CStudent类,包含学号、姓名、语文成绩、英语成绩。编写4大成员函数。要求使用new/delete cin/cout。在main函数中,建立1个学生数组(可以放3个元素),通过键盘输入学生信息,并打印信息。


2、自定义1个链表类,然后在main函数中,建立1个链表对象,然后通过链表的成员函数,进行3个学生信息,加入到链表中,最后,遍历打印学生信息。


//思路:
#include <iostream>
#include <stdlib.h>
#include <string.h>


//void (*printf_student)(void *data);


class CStudent
{


};




void printf_student(void *data)
{




	return;
}



int main()
{
	CStudent stu1(1001,"zhangsan");
	CLink link;
	link.add_node((void *)&stu1);
	link.foreach(printf_student);
	link.destroy(delete_name);
	//link_create();


	return 0;
}



知识点:
链表函数库------->封装成CLink类-----》main函数不是 成员函数----只能通过给工程 新建文件 来完成在main函数里,有1条 语句-----建立1个学生,而且还赋值为 1001 "zhangsan"这里出现了 新的 数据类型 CStudnt-----分清它属于 那个模块     ----很具体的1个数据类型,应该属于应用层  顶层
虽然 也属于 顶层,但CStudent如果放置在自己的 .h  .cpp  更好所以,该顶层 将有  3个文件在main函数里,有1条 语句-----建立 空链表      CList list;
这里出现了 新的 数据类型 CList-----分清它属于 那个模块      -----很抽象,应该属于 底下1层既然是 地下1层,就要求 该类型的 成员变量、参数------不能有顶层的 数据类型----不能有CStudent,CList list 其实等价于 调用了1个 无参构造函数该函数的功能:应该是 给自己的 成员变量head,赋值,而且为NULL

在main函数里,有1条 语句-----给链表里 增加 节点可以考虑用CList的成员函数来实现

该CList的成员函数,可以直接调用 link.h/link.cpp中的 link_add_node()函


数来实现
考虑到 link_add_node()  是再下1层的   
 
该函数里要 先建立1个 CNode节点  
考虑 CNode节点    应为 底下1层
CNode  也通过.h  .cpp来写层:由高 到低


main.cpp
Student.h、Student.cpp

List.h/List.cpp

link.h/link.cpp    pfun数据类型

Node.h/Node.cpp



如何 添加头文件:
原则:
始终都是  上层 调用 下层
调用时,使用下1层的函数-----使用前要加 下1层的函数原型-------用include .h 省事


实现


//1 类间的关系
//组合	-----   组装         学生----成绩
//聚合	-----   聚集         主窗口-----  子窗口


//组合 的使用:
//给学生类  里  放1个  成绩
//成绩-----变量     特殊的变量(类)

//在定义 学生的构造函数时,如何给 chengji变量 赋值?
	//利用 CScore的构造函数 来给 chengji 赋值。
	//引出了  初始化表-------  :chengji(chinese,math,englis)   放置在 函数原型后面(cpp中的,.h不用变)

CStudent::CStudent(int number,char *name,int chinese,int math,int english):chengji(chinese,math,english)//初始化表
{
	this->number=number;
	this->name=new char[strlen(name)+1];
	strcpy(this->name,name);
	//this->chinese=chinese;
	//this->math=math;
	//this->english=english;
	//chengji.CScore(chinese,math,english);   因为CScore()是构造函数,不能这么用
}	


//小技巧:
//调用CStudent的print函数时,可以调用 CScore的print函数

//组合代码:
//main.cpp

#include "Student.h"

int main()
{
	CStudent stu1(1001,"zhangsan",61,62,63);
	stu1.print_student();

	return 0;
}


//Student.h
// Student.h: interface for the CStudent class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_STUDENT_H__6C8339B9_6432_4E34_A210_A960F4A095CC__INCLUDED_)
#define AFX_STUDENT_H__6C8339B9_6432_4E34_A210_A960F4A095CC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Score.h"

class CStudent  
{
public:
	int number;
	char *name;
	//int chinese;
	//int math;
	//int english;
	CScore chengji;
	CStudent();
	virtual ~CStudent();
	CStudent(int number,char *name,int chinese,int math,int english);
	void print_student();

};

#endif // !defined(AFX_STUDENT_H__6C8339B9_6432_4E34_A210_A960F4A095CC__INCLUDED_)


//Student.cpp
// Student.cpp: implementation of the CStudent class.
//
//////////////////////////////////////////////////////////////////////
#include <iostream>
#include "Student.h"

using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CStudent::CStudent()
{

}

CStudent::~CStudent()
{

}

CStudent::CStudent(int number,char *name,int chinese,int math,int english):chengji(chinese,math,english)//初始化表
{
	this->number=number;
	this->name=new char[strlen(name)+1];
	strcpy(this->name,name);
	//this->chinese=chinese;
	//this->math=math;
	//this->english=english;
	//chengji.CScore(chinese,math,english);   因为CScore()是构造函数,不能这么用
}

void CStudent::print_student()
{
	cout<<"number is "<<number<<endl<<"name is "<<name<<endl;
	//cout<<"chines is "<<chengji.chinese
	chengji.print_chengji();
	return;
}


//Score.h
class CScore  
{
public:
	int chinese;
	int math;
	int english;
	CScore();
	CScore(int chinese,int math,int english);
	virtual ~CScore();
	void print_chengji();

};


//Score.cpp
// Score.cpp: implementation of the CScore class.
//
//////////////////////////////////////////////////////////////////////
#include <iostream>
#include "Score.h"

using namespace std;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CScore::CScore()
{

}

CScore::~CScore()
{

}

CScore::CScore(int chinese,int math,int english)
{
	this->chinese=chinese;
	this->math=math;
	this->english=english;		
}

void CScore::print_chengji()
{
	cout<<"chinese is "<<chinese<<"  math is "<<math<<"  english is "<<english<<endl;
	return;
}


 
 
 




















声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
  • 上一篇:没有了
  • 下一篇:没有了
未上传头像