亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

c++面向對象的編程入門篇--類構造函數與析構函數

2019-11-17 05:06:51
字體:
來源:轉載
供稿:網友
請注重,這一節內容是c++的重點,要非凡注重!


我們先說一下什么是構造函數?

上一個教程我們簡單說了關于類的一些基本內容,對于類對象成員的初始化我們始終是建立成員函數然后手工調用該函數對成員進行賦值的,那么在c++中對于類來說有沒有更方便的方式能夠在對象創建的時候就自動初始化成員變量呢,這一點對操作保護成員是至關重要的,答案是肯定的關于c++類成員的初始化,有專門的構造函數來進行自動操作而無需要手工調用,在正式講解之前先看看c++對構造函數的一個基本定義。

1.C++規定,每個類必須有默認的構造函數,沒有構造函數就不能創建對象。

2.若沒有提供任何構造函數,那么c++提供自動提供一個默認的構造函數,該默認構造函數是一個沒有參數的構造函數,它僅僅負責創建對象而不做任何賦值操作。

3.只要類中提供了任意一個構造函數,那么c++就不在自動提供默認構造函數。

4.類對象的定義和變量的定義類似,使用默認構造函數創建對象的時候,假如創建的是靜態或者是全局對象,則對象的位模式全部為0,否則將會是隨即的。



我們來看下面的代碼:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
using namespace std;
class Student
{
public:
Student()//無參數構造函數
{
number = 1;
score = 100;
}
void show();

PRotected:
int number;
int score;

};

void Student::show()
{
cout<<number<<endl<<score<<endl;
}

void main()
{
Student a;
a.show();
cin.get();
}


在類中的定義的和類名相同,并且沒有任何返回類型的Student()就是構造函數,這是一個無參數的構造函數,他在對象創建的時候自動調用,假如去掉Student()函數體內的代碼那么它和c++的默認提供的構造函數等價的。
更多文章 更多內容請看C/C++技術學堂專題,或 構造函數可以帶任意多個的形式參數,這一點和普通函數的特性是一樣的!

下面我們來看一個帶參數的構造函數是如何進行對象的始化操作的。

代碼如下:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
using namespace std;
class Teacher
{
public:
Teacher(char *input_name)//有參數的構造函數
{
name=new char[10];
//name=input_name;//這樣賦值是錯誤的
strcpy(name,input_name);
}
void show();

protected:
char *name;

};

void Teacher::show()
{
cout<<name<<endl;
}

void main()
{
//Teacher a;//這里是錯誤的,因為沒有無參數的構造函數
Teacher a("test");
a.show();
cin.get();
}


我們創建了一個帶有字符指針的帶有形參的Teacher(char *input_name)的構造函數,調用它創建對象的使用類名加對象名稱加擴號和擴號內參數的方式調用,這和調用函數有點類似,但意義也有所不同,因為構造函數是為創建對象而設立的,這里的意義不單純是調用函數,而是創建一個類對象。

一旦類中有了一個帶參數的構造函數而又沒無參數構造函數的時候系統將無法創建不帶參數的對象,所以上面的代碼

Teacher a;

就是錯誤的?。。?


這里還有一處也要注重:

//name=input_name;//這樣賦值是錯誤的

因為name指是指向內存堆區的,假如使用name=input_name;會造成指針指向改變不是指向堆區而是指向棧區,導致在后面調用析構函數delete釋放堆空間出錯!(析構函數的內容我們后面將要介紹)

假如需要調用能夠執行就需要再添加一個沒有參數的構造函數

對上面的代碼改造如下:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
using namespace std;
class Teacher
{
public:
Teacher(char *input_name)
{
name=new char[10];
//name=input_name;//這樣賦值是錯誤的
strcpy(name,input_name);
}
Teacher()//無參數構造函數,進行函數重載
{

}
void show();

protected:
char *name;

};

void Teacher::show()
{
cout<<name<<endl;
}

void main()
{
Teacher test;
Teacher a("test");
a.show();
cin.get();
}
創建一個無闡述的同名的Teacher()無參數函數,一重載方式區分調用,由于構造函數和普通函數一樣具有重載特性所以編寫程序的人可以給一個類添加任意多個構造函數,來使用不同的參數來進行初始話對象! 更多文章 更多內容請看C/C++技術學堂專題,或 現在我們來說一下,一個類對象是另外一類的數據成員的情況,假如有點覺得饒人那么可以簡單理解成:類成員的定義可以相互嵌套定義,一個類的成員可以用另一個類進行定義聲明。


c++規定假如一個類對象是另外一類的數據成員,那么在創建對象的時候系統將自動調用那個類的構造函數。

下面我們看一個例子。

代碼如下:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
using namespace std;
class Teacher
{
public:
Teacher()
{
Director = new char[10];
strcpy(director,"王大力");
}
char *show();
protected:
char *director;
};
char *Teacher::show()
{
return director;
}
class Student
{
public:
Student()
{
number = 1;
score = 100;
}
void show();

protected:
int number;
int score;
Teacher teacher;//這個類的成員teacher是用Teacher類進行創建并初始化的

};

void Student::show()
{
cout<<teacher.show()<<endl<<number<<endl<<score<<endl;
}

void main()
{
Student a;
a.show();
Student b[5];
for(int i=0; i<sizeof(b)/sizeof(Student); i++)
{
b[i].show();
}
cin.get();
}


上面代碼中的Student類成員中teacher成員是的定義是用類Teacher進行定義創建的,那么系統碰到創建代碼的時候就會自動調用Teacher類中的Teacher()構造函數對對象進行初始化工作!

這個例子說明類的分工很明確,只有碰到自己的對象的創建的時候才自己調用自己的構造函數! 更多文章 更多內容請看C/C++技術學堂專題,或 一個類可能需要在構造函數內動態分配資源,那么這些動態開辟的資源就需要在對象不復存在之前被銷毀掉,那么c++類的析構函數就提供了這個方便。


析構函數的定義:析構函數也是非凡的類成員函數,它沒有返回類型,沒有參數,不能隨意調用,也沒有重載,只有在類對象的生命期結束的時候,由系統自動調用。

析構函數與構造函數最主要大不同就是在于調用期不同,構造函數可以有參數可以重載!

我們前面例子中的Teacher類中就使用new操作符進行了動態堆內存的開辟,由于上面的代碼缺少析構函數,所以在程序結束后,動態開辟的內存空間并沒有隨著程序的結束而小時,假如沒有析構函數在程序結束的時候逐一清除被占用的動態堆空間那么就會造成內存泄露,使系統內存不斷減少系統效率將大大降低!

那么我們將如何編寫類的析構函數呢?

析構函數可以的特性是在程序結束的時候逐一調用,那么正好與構造函數的情況是相反,屬于互逆特性,所以定義析構函數因使用"~"符號(邏輯非運算符),表示它為膩構造函數,加上類名稱來定義。

看如下代碼:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
#include <string>
using namespace std;
class Teacher
{
public:
Teacher()
{
director = new char[10];
strcpy(director,"王大力");
//director = new string;
// *director="王大力";//string情況賦值
}
~Teacher()
{
cout<<"釋放堆區director內存空間1次";
delete[] director;
cin.get();
}
char *show();
protected:
char *director;
//string *director;
};
char *Teacher::show()
{
return director;
}
class Student
{
public:
Student()
{
number = 1;
score = 100;
}
void show();

protected:
int number;
int score;
Teacher teacher;

};

void Student::show()
{
cout<<teacher.show()<<endl<<number<<endl<<score<<endl;
}
void main()
{
Student a;
a.show();
Student b[5];
for(int i=0; i<sizeof(b)/sizeof(Student); i++)
{
b[i].show();
}
cin.get();
}


上面的代碼中我們為Teacher類添加了一個名為~Teacher()的析構函數用于清空堆內存。

建議大家編譯運行代碼觀察調用情況,程序將在結束前也就是對象生命周期結束的時候自動調用~Teacher()

~Teache()中的delete[] director;就是清除堆內存的代碼,這與我們前面一開始提到的。

name=input_name;//這樣賦值是錯誤的

有直接的關系,因為delete操作符只能清空堆空間而不能清楚桟空間,假如強行清除棧空間內存的話將導致程序崩潰?。? 更多文章 更多內容請看C/C++技術學堂專題,或 前面我們已經簡單的說了類的構造函數和析構函數,我們知道一個類的成員可以是另外一個類的對象,構造函數答應帶參數,那么我們可能會想到上面的程序我們可以在類中把Student類中的teacher成員用帶參數的形式調用Student類的構造函數,不必要再在Teacher類中進行操作,
由于這一點構想我們把程序修改成如下形式:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
#include <string>

using namespace std;
class Teacher
{
public:
Teacher(char *temp)
{
director = new char[10];
strcpy(director,temp);
}
~Teacher()
{
cout<<"釋放堆區director內存空間1次";
delete[] director;
cin.get();
}
char *show();
protected:
char *director;
};
char *Teacher::show()
{
return director;
}
class Student
{
public:
Student()
{
number = 1;
score = 100;
}
void show();

protected:
int number;
int score;
Teacher teacher("王大力");//錯誤,一個類的成員假如是另外一個類的對象的話,不能在類中使用帶參數的構造函數進行初始化

};

void Student::show()
{
cout<<teacher.show()<<endl<<number<<endl<<score<<endl;
}
void main()
{
Student a;
a.show();
Student b[5];
for(int i=0; i<sizeof(b)/sizeof(Student); i++)
{
b[i].show();
}
cin.get();
}



可是很遺憾,程序不能夠被編譯成功,為什么呢?

因為:類是一個抽象的概念,并不是一個實體,并不能包含屬性值(這里來說也就是構造函數的參數了),只有對象才占有一定的內存空間,含有明確的屬性值!


這一個問題是類成員初始化比較尷尬的一個問題,是不是就沒有辦法解決了呢?呵呵。。。。。。

c++為了解決此問題,有一個很獨特的方法,下一小節我們將介紹。 更多文章 更多內容請看C/C++技術學堂專題,或 對于上面的那個"尷尬"問題,我們可以在構造函數頭的后面加上:號并指定調用哪那個類成員的構造函數來解決!

教程寫到這里的時候對比了很多書籍,發現幾乎所有的書都把這一章節叫做構造類成員,筆者在此覺得有所不妥,因為從讀音上輕易混淆概念,所以把這一小節的名稱改為構造類的成員比較合適!

代碼如下:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
using namespace std;
class Teacher
{
public:
Teacher(char *temp)
{
director = new char[10];
strcpy(director,temp);
}
~Teacher()
{
cout<<"釋放堆區director內存空間1次";
delete[] director;
cin.get();
}
char *show();
protected:
char *director;
};
char *Teacher::show()
{
return director;
}
class Student
{
public:
Student(char *temp):teacher(temp)
{
number = 1;
score = 100;
}
void show();

protected:
int number;
int score;
Teacher teacher;

};

void Student::show()
{
cout<<teacher.show()<<endl<<number<<endl<<score<<endl;
}
void main()
{
Student a("王大力");
a.show();
//Student b[5]("王大力"); //這里這么用是不對的,數組不能夠使用帶參數的構造函數,以后我們將具體介紹vector類型
// for(int i=0; i<sizeof(b)/sizeof(Student); i++)
//{
// b[i].show();
//}

cin.get();
}




大家可以發現最明顯的改變在這里

Student(char *temp):teacher(temp)

冒號后的teacher就是告訴調用Student類的構造函數的時候把參數傳遞給成員teacher的Teacher類的構造函數,這樣一來我們就成功的在類體外對teacher成員進行了初始化,既方便也高效,這種冒號后指定調用某成員構造函數的方式,可以同時制定多個成員,這一特性使用逗號方式,例如:

Student(char *temp):teacher(temp),abc(temp),def(temp)


由冒號后可指定調用哪那個類成員的構造函數的特性,使得我們可以給類的常量和引用成員進行初始化成為可能。

我們修改上面的程序,得到如下代碼:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
#include <string>
using namespace std;
class Teacher
{
public:
Teacher(char *temp)
{
director = new char[10];
strcpy(director,temp);
}
~Teacher()
{
cout<<"釋放堆區director內存空間1次";
delete[] director;
cin.get();
}
char *show();
protected:
char *director;
};
char *Teacher::show()
{
return director;
}
class Student
{
public:
Student(char *temp,int &pk):teacher(temp),pk(pk),ps(10)
{
number = 1;
score = 100;
}
void show();

protected:
int number;
int score;
Teacher teacher;
int &pk;
const int ps;

};

void Student::show()
{
cout<<teacher.show()<<endl<<number<<endl<<score<<endl<<pk<<endl<<ps<<endl;
}
void main()
{
char *t_name="王大力";
int b=99;
Student a(t_name,b);
a.show();
cin.get();
}



改變之處最重要的在這里Student(char *temp,int &pk):teacher(temp),pk(pk),ps(10)

調用的時候我們使用

Student a(t_name,b);

我們將b的地址傳遞給了int &pk這個引用,使得Student類的引用成員pk和常量成員ps進行了成功的初始化。

但是細心的人會發現,我們在這里使用的初始化方式并不是在構造函數內進行的,而是在外部進行初始化的,的確,在冒號后和在構造函數括號內的效果是一樣的,但和teacher(temp)所不同的是,pk(pk)的括號不是調用函數的意思,而是賦值的意思,我想有些讀者可能不清楚新標準的c++對變量的初始化是答應使用括號方式的,int a=10和int a(10)的等價的,但冒號后是不答應使用=方式只答應()括號方式,所以這里只能使用pk(pk)而不能是pk=pk了。 更多文章 更多內容請看C/C++技術學堂專題,或 這一小節的內容是說對象構造的順序的,對象構造的順序直接關系程序的運行結果,有時候我們寫的程序不錯,但運行出來的結果卻超乎我們的想象,了解c++對對象的構造順序有助于解決這些問題。


c++規定,所有的全局對象和全局變量一樣都在主函數main()之前被構造,函數體內的靜態對象則只構造一次,也就是說只在首次進入這個函數的時候進行構造!

代碼如下:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
#include <string>
using namespace std;

class Test
{
public:
Test(int a)
{
kk=a;
cout<<"構造參數a:"<<a<<endl;
}
public:
int kk;
};

void fun_t(int n)

{
static Test a(n);
//static Test a=n;//這么寫也是對的
cout<<"函數傳入參數n:"<<n<<endl;
cout<<"對象a的屬性kk的值:"<<a.kk<<endl;
}
Test m(100);
void main()
{
fun_t(20);
fun_t(30);
cin.get();
}




下面我們來看一下,類成員的構造順序的問題。

先看下面的代碼:


//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>
using namespace std;

class Test
{
public:
Test(int j):pb(j),pa(pb+5)
{

}
public:
int pa;
int pb;
};
void main()
{
Test a(10);
cout<<a.pa<<endl;
cout<<a.pb<<endl;
cin.get();
}


上面的程序在代碼上是沒有任何問題的,但運行結果可能并不如人意。

pa并沒有得到我們所希望的15而是一個隨機的任意地址的值。

這又是為什么呢?

類成員的構造是按照在類中定義的順序進行的,而不是按照構造函數說明后的冒號順序進行構造的,這一點需要記住?。。。?! 更多文章 更多內容請看C/C++技術學堂專題,或

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人免费观看| 欧美一级大片在线观看| 欧美成人手机在线| 精品免费在线视频| 欧美最猛性xxxx| 国产精品亚洲欧美导航| 91久久久久久久久久久久久| 亚洲男女性事视频| 高清日韩电视剧大全免费播放在线观看| 国产欧美日韩丝袜精品一区| 日韩欧美在线观看| 日韩国产中文字幕| 欧美电影《睫毛膏》| 亚洲自拍偷拍区| 欧美另类老女人| 国产精品色视频| 日韩在线欧美在线| 欧美成人合集magnet| 超碰91人人草人人干| 久久精品国产亚洲7777| 日韩在线视频观看| 91大神福利视频在线| 久久精品国产99国产精品澳门| 欧美日韩成人在线观看| 欧美激情精品久久久久久大尺度| 国产成人精品亚洲精品| 日韩美女在线播放| 国产日产久久高清欧美一区| 国产成人拍精品视频午夜网站| 18久久久久久| 日韩欧美成人免费视频| 欧美日韩国产影院| 九九热精品视频| 亚洲视频在线观看网站| 在线看日韩av| 欧美专区国产专区| 中文字幕亚洲一区二区三区五十路| 国产一区二区三区视频在线观看| 欧美成人免费一级人片100| 亚洲最大福利视频| 日韩免费电影在线观看| 国产色婷婷国产综合在线理论片a| 国产脚交av在线一区二区| 欧美中文字幕在线播放| 奇门遁甲1982国语版免费观看高清| 成人免费淫片视频软件| 久热精品视频在线观看一区| 亚洲第一综合天堂另类专| 国产精品wwwwww| 大伊人狠狠躁夜夜躁av一区| 精品亚洲一区二区三区四区五区| 在线观看精品自拍私拍| 日本精品视频在线观看| 久久艹在线视频| 亚洲最大成人网色| 亚洲欧美另类在线观看| 亚洲一区二区中文字幕| 成人精品一区二区三区| 亚洲精品日产aⅴ| 亚洲香蕉av在线一区二区三区| 欧美大片欧美激情性色a∨久久| 国产91精品最新在线播放| 欧美在线观看日本一区| 亚洲一区二区三区在线免费观看| 久久久精品久久久| 国产啪精品视频网站| 欧美日韩成人免费| 日韩欧美a级成人黄色| 欧美大胆在线视频| 亚洲成人av在线播放| 欧美激情日韩图片| 精品久久久香蕉免费精品视频| 国产精品第七影院| 国产视频精品xxxx| 日产精品99久久久久久| 国产在线精品播放| 欧美老女人bb| 国产精品成av人在线视午夜片| 国产成人aa精品一区在线播放| 在线日韩日本国产亚洲| 一夜七次郎国产精品亚洲| 日韩三级成人av网| 黑人巨大精品欧美一区二区| 精品国产乱码久久久久久虫虫漫画| 中文字幕精品在线| 91精品国产九九九久久久亚洲| 成人h片在线播放免费网站| 国产精品久久久久久影视| 日韩欧美精品免费在线| 日韩欧美高清在线视频| 久久99国产综合精品女同| 亚洲综合在线播放| 琪琪第一精品导航| 欧美午夜丰满在线18影院| 欧美一级大胆视频| 国产精品自在线| 亚洲白拍色综合图区| 亚洲天堂av电影| 日本国产精品视频| 欧美人交a欧美精品| 中文字幕精品影院| 中文字幕精品在线视频| 精品国产一区二区三区四区在线观看| 欧美激情网友自拍| 一本色道久久综合亚洲精品小说| 在线观看日韩视频| 日本精品免费一区二区三区| 久久久久久成人精品| 国产91亚洲精品| 奇米影视亚洲狠狠色| 久久天天躁狠狠躁夜夜av| 中文字幕日韩欧美精品在线观看| 成人网址在线观看| 亚洲一区二区三区xxx视频| 91在线国产电影| 国产精品久久91| 亚洲最新视频在线| 久久精品国产成人精品| 国产精品偷伦一区二区| 国产精品一区二区三区久久久| 一区二区三区亚洲| 欧美电影在线观看完整版| 久久精品夜夜夜夜夜久久| 欧美激情视频在线观看| 国产婷婷成人久久av免费高清| 欧美极品少妇xxxxⅹ裸体艺术| 精品综合久久久久久97| 久久夜色精品国产亚洲aⅴ| 最近2019年日本中文免费字幕| 成人网址在线观看| 欧美专区第一页| 国产精品美女视频网站| 国产精品91久久久| 69视频在线播放| 成人妇女淫片aaaa视频| 久久国产精品视频| 国产成人精品久久| www.美女亚洲精品| 欧美性xxxxx极品| 亚洲国产精品人人爽夜夜爽| 欧美在线一区二区视频| 91精品国产免费久久久久久| 国产精品偷伦免费视频观看的| 中文字幕日韩欧美在线视频| 国产精选久久久久久| 国产精品91一区| 久久精品成人欧美大片古装| 亚洲精品mp4| 91精品国产免费久久久久久| 日韩精品视频在线播放| 日韩欧美在线观看| 亚洲精品女av网站| 国产成人一区二区三区电影| 日韩中文字幕视频在线观看| 欧美激情图片区| 成人网址在线观看| 色妞色视频一区二区三区四区| 理论片在线不卡免费观看| 欧美性一区二区三区| 性欧美xxxx视频在线观看| 最近2019中文字幕一页二页| 亚洲欧美日韩中文视频| 亚洲free性xxxx护士白浆| 国语自产精品视频在线看一大j8|