析構函數
自動調用-------跟 構造函數相近析構函數
特點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;
}