C++之赋值函数和析构函数
析构函数
自动调用-------跟 构造函数相近析构函数
特点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。
- 上一篇:没有了
- 下一篇:没有了