最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++初階教程之類(lèi)和對(duì)象

 更新時(shí)間:2022年02月07日 14:57:44   作者:AKA你的閨蜜  
C++是面向?qū)ο缶幊痰?這也是C++與C語(yǔ)言的最大區(qū)別,而類(lèi)和對(duì)象就是C++面向?qū)ο蟮幕A(chǔ),下面這篇文章主要給大家介紹了關(guān)于C++初階教程之類(lèi)和對(duì)象的相關(guān)資料,需要的朋友可以參考下

類(lèi)和對(duì)象<上>

面向?qū)ο?/p>

一直以來(lái)都是面向過(guò)程編程比如C語(yǔ)言,直到七十年代面向過(guò)程編程在開(kāi)發(fā)大型程序時(shí)表現(xiàn)出不足,計(jì)算機(jī)界提出了面向?qū)ο笏枷耄∣bject Oriented Programming),其中核心概念是類(lèi)和對(duì)象,面向?qū)ο笕筇匦允欠庋b、繼承和多態(tài)。

面向過(guò)程和面向?qū)ο笾皇怯?jì)算機(jī)編程中兩種側(cè)重點(diǎn)不同的思想,面向過(guò)程算是一種最為實(shí)際的思考方式,其中重要的是模塊化的思想,面向過(guò)程更注重過(guò)程、動(dòng)作或者說(shuō)事件的步驟。就算是面向?qū)ο笠彩呛忻嫦蜻^(guò)程的思想,對(duì)比面向過(guò)程,面向?qū)ο蟮姆椒ㄖ饕前咽挛锝o對(duì)象化,認(rèn)為事物都可以轉(zhuǎn)化為一系列對(duì)象和它們之間的關(guān)系,更符合人對(duì)事物的認(rèn)知方式。

用外賣(mài)系統(tǒng)舉例,面向過(guò)程思想就會(huì)將訂餐、取餐、送餐、接單等等步驟模塊化再一個(gè)一個(gè)實(shí)現(xiàn),體現(xiàn)到程序中就是一個(gè)個(gè)的函數(shù)。面向?qū)ο笏枷霑?huì)將整個(gè)流程歸結(jié)為對(duì)象和對(duì)象間的關(guān)系,也就是商家、騎手和用戶(hù)三者和他們的關(guān)系,體現(xiàn)到程序中就是類(lèi)的設(shè)計(jì)。

面向?qū)ο笫且粋€(gè)廣泛而深刻的思想,不可能一時(shí)半會(huì)就理解透徹,需要再學(xué)習(xí)和工作中慢慢體會(huì)。

C++不像Java是純面向?qū)ο笳Z(yǔ)言,C++基于面向?qū)ο蟮旨嫒軨所以也可以面向過(guò)程。

1. 類(lèi)的定義

//C
struct Student {
	char name[20];
	int age;
	int id;
};
struct Student s;
strcpy(s.name, "yyo");
s.age = 18;
s.id = 11;
//C++
struct Student {
	//成員變量
	char _name[20];
	int _age;
	int _id;
	//成員方法
	void Init(const char* name, int age, int id) {
		strcpy(_name, name);
		_age = age;
		_id = id;
	}
	void Print() {
		cout << _name << endl;
		cout << _age << endl;
		cout << _id << endl;
	}
};
s1.Init("yyo", 19, 1);
s1.Print();
s2.Init("yyx", 18, 2);
s2.Print();

從上述代碼可以看出,在C語(yǔ)言中,結(jié)構(gòu)體中只能定義變量,就相當(dāng)于是個(gè)多個(gè)變量的集合,而且操作成員變量的方式相較于C++更加繁瑣且容易出現(xiàn)錯(cuò)誤。

由于C++兼容C,故C++中定義類(lèi)有兩個(gè)關(guān)鍵字分別是struct和class,結(jié)構(gòu)體在C++中也升級(jí)成了類(lèi),類(lèi)名可以直接作類(lèi)型使用。類(lèi)與結(jié)構(gòu)體不同的地方在于,類(lèi)中不僅可以定義變量,還可以定義方法或稱(chēng)函數(shù)。

C++中更多用class定義類(lèi),用class定義的類(lèi)和struct定義的類(lèi)在訪問(wèn)限定權(quán)限上稍有不同。

class className {
    // ...
};

class是類(lèi)的關(guān)鍵字,className是類(lèi)的名字,{}中的內(nèi)容是類(lèi)體。類(lèi)中的元素即變量和函數(shù)都叫類(lèi)的成員,其中類(lèi)的成員變量稱(chēng)為類(lèi)的屬性或是類(lèi)的數(shù)據(jù),類(lèi)的函數(shù)成為類(lèi)的方法或成員函數(shù)。

2. 類(lèi)的封裝

面向?qū)ο缶幊讨v究個(gè)“封裝”二字,封裝體現(xiàn)在兩方面,一是將數(shù)據(jù)和方法都放到類(lèi)中封裝起來(lái),二是給成員增加訪問(wèn)權(quán)限的限制。

2.1 訪問(wèn)限定修飾符

C++共有三個(gè)訪問(wèn)限定符,分別為公有public,保護(hù)protect,私有private。

  • public修飾的成員可以在類(lèi)外直接訪問(wèn),private和protect修飾的成員在類(lèi)外不能直接訪問(wèn)。
  • class類(lèi)中成員默認(rèn)訪問(wèn)權(quán)限為private,struct類(lèi)中默認(rèn)為public。
  • 從訪問(wèn)限定符出現(xiàn)的位置到下一個(gè)訪問(wèn)限定符出現(xiàn)的位置之間都是該訪問(wèn)限定符的作用域。

和public相比,private和protect在這里是類(lèi)似的,它二者具體區(qū)別會(huì)在之后的繼承中談到。封裝的意義就在于規(guī)范成員的訪問(wèn)權(quán)限,放開(kāi)struct類(lèi)的權(quán)限是因?yàn)橐嫒軨。

封裝的意義就在于規(guī)范成員的訪問(wèn)權(quán)限,更好的管理類(lèi)的成員,一般建議是將成員的訪問(wèn)權(quán)限標(biāo)清楚,不要用類(lèi)的默認(rèn)規(guī)則。

class Student {
private:
	//成員變量
	char _name[20];
	int _age;
	int _id;
public:
	//成員方法
	void Init(const char* name, int age, int id) {
		strcpy(_name, name);
		_age = age;
		_id = id;
	}
	void Print() {
		cout << _name << endl;
		cout << _age << endl;
		cout << _id << endl;
	}
};

注意,訪問(wèn)限定修飾符只在編譯階段起作用,之后不會(huì)對(duì)變量和函數(shù)造成任何影響。

2.2 類(lèi)的封裝

面向?qū)ο笕筇匦允欠庋b、繼承和多態(tài)。類(lèi)和對(duì)象的學(xué)習(xí)階段,只強(qiáng)調(diào)類(lèi)和對(duì)象的封裝機(jī)制。封裝的定義是:將數(shù)據(jù)和操作數(shù)據(jù)的方法放到類(lèi)中有機(jī)結(jié)合,對(duì)外隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅公開(kāi)交互的接口。

封裝的本質(zhì)是一種管理機(jī)制。對(duì)比C語(yǔ)言版的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)可以看到,沒(méi)有封裝并將結(jié)構(gòu)的成員全部暴露出來(lái)是危險(xiǎn)的且容易出錯(cuò),但調(diào)用結(jié)構(gòu)提供的接口卻不易出錯(cuò)。一般不允許輕易的操作在函數(shù)外操作和改變結(jié)構(gòu),這便是封裝的好處。面向過(guò)程只有針對(duì)函數(shù)的封裝,而面向?qū)ο缶幊烫岢隽烁尤娴姆庋b機(jī)制,使得代碼更加安全且易于操作。

class Stack {
public:
	void Init();
	void Push(STDataType x);
	void Pop();
	STDataType Top();
	int Size();
	bool Empty();
	void Destroy();
private:
	STDataType* _a;
	int _top;
	int _capacity;
};

3. 類(lèi)的使用

3.1 類(lèi)的作用域

類(lèi)定義了一個(gè)新的作用域,類(lèi)中所有成員都在類(lèi)的作用域中。

  • 若直接在類(lèi)內(nèi)定義函數(shù)體,編譯器默認(rèn)將類(lèi)內(nèi)定義的函數(shù)當(dāng)作內(nèi)聯(lián)函數(shù)處理,在滿(mǎn)足內(nèi)聯(lián)函數(shù)的要求的情況下。
  • 在類(lèi)外定義成員函數(shù)時(shí),需要使用域作用限定符::指明該成員歸屬的類(lèi)域。如圖所示:

一般情況下,更多是采用像數(shù)據(jù)結(jié)構(gòu)時(shí)期那樣,聲明和定義分離的方式。

3.2 類(lèi)的實(shí)例化

用類(lèi)創(chuàng)建對(duì)象的過(guò)程,就稱(chēng)為類(lèi)的實(shí)例化。

  1. 類(lèi)只是一個(gè)“模型”,限定了類(lèi)的性質(zhì),但并沒(méi)有為其分配空間。
  2. 由類(lèi)可以實(shí)例化得多個(gè)對(duì)象,對(duì)象在內(nèi)存中占據(jù)實(shí)際的空間,用于存儲(chǔ)類(lèi)成員變量。

類(lèi)和對(duì)象的關(guān)系,就與類(lèi)型和變量的關(guān)系一樣,可以理解為圖紙和房子的關(guān)系。

4. 類(lèi)對(duì)象的存儲(chǔ)

既然類(lèi)中既有成員變量又有成員函數(shù),那么一個(gè)類(lèi)的對(duì)象中包含了什么?類(lèi)對(duì)象如何存儲(chǔ)?

class Stack {
public:
	void Init();
	void Push(int x);
	// ...
private:
	int* _a;
	int _top;
	int _capacity;
};
Stack st;
cout << sizeof(Stack) << endl;
cout << sizeof(st) << endl;

如果類(lèi)成員函數(shù)也存放在對(duì)象中,實(shí)例化多個(gè)對(duì)象時(shí),各個(gè)對(duì)象的成員變量相互獨(dú)立,但成員函數(shù)是相同的,相同的代碼存儲(chǔ)多份浪費(fèi)空間。因此,C++對(duì)象中僅存儲(chǔ)類(lèi)變量,成員函數(shù)存放在公共代碼段。

類(lèi)的大小就是該類(lèi)中成員變量之和,要求內(nèi)存對(duì)齊,和結(jié)構(gòu)體一樣。注意,空類(lèi)的大小為1個(gè)字節(jié),用來(lái)標(biāo)識(shí)這個(gè)對(duì)象的存在。

空類(lèi)的大小若為0,相當(dāng)于內(nèi)存中沒(méi)有為該類(lèi)所創(chuàng)對(duì)象分配空間,等價(jià)于對(duì)象不存在,所以是不可能的。

接下來(lái)都使用棧和日期類(lèi)來(lái)理解類(lèi)和對(duì)象中的知識(shí)。

5. this 指針

class Date {
public:
	void Init(int year, int month, int day) {
		//year = year;//Err
		//1.
        _year = year;
        //2.
        Date::month = month;
        //3.
		this->day = day;
	}
private:
	int _year;
	int month;
	int day;
};

如果成員變量和形參重名的話(huà),在Init函數(shù)中賦值就會(huì)優(yōu)先使用形參導(dǎo)致成員變量沒(méi)有被初始化,這種問(wèn)題有三種解決方案:

  1. 在成員變量名前加_,以區(qū)分成員和形參。
  2. 使用域訪問(wèn)修飾符::,指定前面的變量是成員變量。
  3. 使用 this 指針。

5.1 this 指針的定義

d1._year;的意義是告訴編譯器到d1這個(gè)對(duì)象中查找變量_year的地址。但函數(shù)并不存放在類(lèi)對(duì)象中,那d1.Print();的意義是什么?

如圖所示,d1,d2兩個(gè)對(duì)象調(diào)用存儲(chǔ)在公共代碼區(qū)的Print函數(shù),函數(shù)體中并沒(méi)有區(qū)分不同對(duì)象,如何做到區(qū)分不同對(duì)象的調(diào)用呢?

C++中通過(guò)引入 this 指針解決該問(wèn)題,C++編譯器給每個(gè)非靜態(tài)的成員函數(shù)增加了一個(gè)隱藏的參數(shù)叫 this 指針。this 指針指向當(dāng)前調(diào)用對(duì)象,函數(shù)體中所有對(duì)成員變量的操作都通過(guò)該指針訪問(wèn),但這些操作由編譯器自動(dòng)完成,不需要主動(dòng)傳遞。

如圖所示,在傳參時(shí)隱藏地傳入了對(duì)象的指針,形參列表中也對(duì)應(yīng)隱藏增加了對(duì)象指針,函數(shù)體中的成員變量前也隱藏了 this 指針。

5.2 this 指針的特性

this是C++的一個(gè)關(guān)鍵字,代表當(dāng)前對(duì)象的指針。this 指針是成員函數(shù)第一個(gè)隱含的指針形參,一般由寄存器傳遞不需要主動(dòng)傳參。

  1. 調(diào)用成員函數(shù)時(shí),不可以顯式傳入 this 指針,成員函數(shù)參數(shù)列表也不可顯示聲明 this 指針。
  2. 但成員函數(shù)中可以顯式使用 this 指針。
  3. this 的類(lèi)型為classType* const,加const是為了防止 this 指針被改變。
  4. this 指針本質(zhì)上是成員函數(shù)的形參,函數(shù)被調(diào)用時(shí)對(duì)象地址傳入該指針,所以 this 指針是形參存儲(chǔ)在函數(shù)棧幀中,對(duì)象中不存儲(chǔ)this指針。

Example 1和2哪個(gè)會(huì)出現(xiàn)問(wèn)題,出什么問(wèn)題?

class A {
public:
	void Printa() {
		cout <<  _a << endl;
	}
	void Show() {
		cout << "Show()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* a = nullptr;
	//1.
	a->Show();
	//2.
	a->Printa();
	return 0;
}

函數(shù)沒(méi)有存儲(chǔ)在對(duì)象中,所以調(diào)用函數(shù)并不會(huì)訪問(wèn)空指針a,僅是空指針作參數(shù)傳入成員函數(shù)而已。二者沒(méi)有程序語(yǔ)法錯(cuò)誤,所以編譯一定通過(guò)。

調(diào)用Show()函數(shù)沒(méi)有訪問(wèn)對(duì)象中的內(nèi)容,不存在訪問(wèn)空指針的問(wèn)題。調(diào)用Print()函數(shù)需到a指針?biāo)笇?duì)象中訪問(wèn)成員_a,所以訪問(wèn)空指針程序崩潰。

類(lèi)和對(duì)象<中>

默認(rèn)成員函數(shù)

一個(gè)對(duì)象都要要對(duì)其進(jìn)行初始化,釋放空間,拷貝復(fù)制等等操作,像棧結(jié)構(gòu)不初始化直接壓棧就會(huì)報(bào)錯(cuò)。由于這些操作經(jīng)常使用或是必不可少,在設(shè)計(jì)之初就被放到類(lèi)中作為默認(rèn)生成的成員函數(shù)使用,解決了C語(yǔ)言的一些不足之處。

C++在設(shè)計(jì)類(lèi)的默認(rèn)成員函數(shù)的機(jī)制較為復(fù)雜,一個(gè)類(lèi)有6個(gè)默認(rèn)的成員函數(shù),分別為構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、賦值運(yùn)算符重載、T* operator&()const T* operator&()const。他們都是特殊的成員函數(shù),這些特殊函數(shù)不能被當(dāng)作常規(guī)函數(shù)調(diào)用。

默認(rèn)的意思是我們不寫(xiě)編譯器也會(huì)自動(dòng)生成一份在類(lèi)里,如果我們寫(xiě)了編譯器就不生成了。自動(dòng)生成默認(rèn)函數(shù)有的時(shí)候功能不夠全面,還是得自己寫(xiě)。

1. 構(gòu)造函數(shù)

1.2 構(gòu)造函數(shù)的定義

構(gòu)造函數(shù)和析構(gòu)函數(shù)分別是完成初始化和清理資源的工作。構(gòu)造函數(shù)就相當(dāng)于數(shù)據(jù)結(jié)構(gòu)時(shí)期我們寫(xiě)的初始化Init函數(shù)。

構(gòu)造函數(shù)是一個(gè)特殊的函數(shù),名字與類(lèi)名相同,創(chuàng)建類(lèi)對(duì)象時(shí)被編譯器自動(dòng)調(diào)用用于初始化每個(gè)成員變量,并且在對(duì)象的生命周期中只調(diào)用一次。

2.2 構(gòu)造函數(shù)的特性

構(gòu)造函數(shù)雖然叫構(gòu)造函數(shù),但構(gòu)造函數(shù)的工作并不是開(kāi)辟空間創(chuàng)建對(duì)象,而初始化對(duì)象中的成員變量。

  • 函數(shù)名和類(lèi)名相同,且無(wú)返回類(lèi)型。
  • 對(duì)象實(shí)例化時(shí)由編譯器自動(dòng)調(diào)用其對(duì)應(yīng)的構(gòu)造函數(shù)。
  • 構(gòu)造函數(shù)支持函數(shù)重載。
//調(diào)用無(wú)參的構(gòu)造函數(shù)
Date d1;
Date d2(); //Err - 函數(shù)聲明
//調(diào)用帶參的構(gòu)造函數(shù)
Date d2(2020,1,18);

注意,調(diào)用構(gòu)造函數(shù)只能在對(duì)象實(shí)例化的時(shí)候,且調(diào)用無(wú)參的構(gòu)造函數(shù)不能帶括號(hào),否則會(huì)當(dāng)成函數(shù)聲明。

  • 若類(lèi)中沒(méi)有顯式定義構(gòu)造函數(shù),程序默認(rèn)創(chuàng)建的構(gòu)造函數(shù)是無(wú)參無(wú)返回類(lèi)型的。一旦顯式定義了編譯器則不會(huì)生成。
  • 無(wú)參的構(gòu)造函數(shù)、全缺省的構(gòu)造函數(shù)和默認(rèn)生成的構(gòu)造函數(shù)都可以是默認(rèn)構(gòu)造函數(shù)(不傳參也可以調(diào)用的構(gòu)造函數(shù)),且防止沖突默認(rèn)構(gòu)造函數(shù)只能有一個(gè)。

默認(rèn)構(gòu)造函數(shù)初始化規(guī)則

從上圖可以看出,默認(rèn)生成的構(gòu)造函數(shù)對(duì)內(nèi)置類(lèi)型的成員變量不進(jìn)行有效初始化。其實(shí),編譯器默認(rèn)生成的構(gòu)造函數(shù)僅對(duì)自定義類(lèi)型進(jìn)行初始化,初始化的方式是在創(chuàng)建該自定義類(lèi)型的成員變量后調(diào)用它的構(gòu)造函數(shù)。倘若該自定義類(lèi)型的類(lèi)也是默認(rèn)生成的構(gòu)造函數(shù),那結(jié)果自然也沒(méi)有被有效初始化。

默認(rèn)生成的構(gòu)造函數(shù)對(duì)內(nèi)置類(lèi)型的成員變量不作處理,對(duì)自定義類(lèi)型成員會(huì)調(diào)用它們的構(gòu)造函數(shù)來(lái)初始化自定義類(lèi)型成員變量。

一個(gè)類(lèi)中最好要一個(gè)默認(rèn)構(gòu)造函數(shù),因?yàn)楫?dāng)該類(lèi)對(duì)象被當(dāng)作其他類(lèi)的成員時(shí),系統(tǒng)只會(huì)調(diào)用默認(rèn)的構(gòu)造函數(shù)。

目前還只是了解掌握基本的用法,對(duì)構(gòu)造函數(shù)在之后還會(huì)再談。

2. 析構(gòu)函數(shù)

析構(gòu)函數(shù)同樣是個(gè)特殊的函數(shù),負(fù)責(zé)清理和銷(xiāo)毀一些類(lèi)中的資源。

2.1 析構(gòu)函數(shù)的定義

與構(gòu)造函數(shù)的功能相反,析構(gòu)函數(shù)負(fù)責(zé)銷(xiāo)毀和清理資源。但析構(gòu)函數(shù)不是完成對(duì)象的銷(xiāo)毀,對(duì)象是main函數(shù)棧幀中的局部變量,所以是隨 main 函數(shù)棧幀創(chuàng)建和銷(xiāo)毀的。析構(gòu)函數(shù)會(huì)在對(duì)象銷(xiāo)毀時(shí)自動(dòng)調(diào)用,主要清理的是對(duì)象中創(chuàng)建的一些成員變量比如動(dòng)態(tài)開(kāi)辟的空間等。

2.2 析構(gòu)函數(shù)的特性

  • 析構(gòu)函數(shù)的名字是~加類(lèi)名,同樣是無(wú)參無(wú)返回類(lèi)型,故不支持重載。
  • 一個(gè)類(lèi)中有且僅有一個(gè)析構(gòu)函數(shù),同樣若未顯式定義,編譯器自動(dòng)生成默認(rèn)的析構(gòu)函數(shù)。
  • 對(duì)象生命周期結(jié)束時(shí),系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)完成清理工作。
  • 多個(gè)對(duì)象調(diào)用析構(gòu)函數(shù)的順序和創(chuàng)建對(duì)象的順序是相反的,因?yàn)槟膫€(gè)對(duì)象先壓棧哪個(gè)對(duì)象就后銷(xiāo)毀。

調(diào)用對(duì)象后自動(dòng)調(diào)用析構(gòu)函數(shù),這樣的機(jī)制可以避免忘記釋放空間以免內(nèi)存泄漏的問(wèn)題。不一定所有類(lèi)都需要析構(gòu)函數(shù),但對(duì)于有些類(lèi)如棧就很方便。

默認(rèn)析構(gòu)函數(shù)清理規(guī)則

和默認(rèn)生成的構(gòu)造函數(shù)類(lèi)似,默認(rèn)生成的析構(gòu)函數(shù)同樣對(duì)內(nèi)置類(lèi)型的成員變量不作處理,只在對(duì)象銷(xiāo)毀時(shí)對(duì)自定義類(lèi)型的成員會(huì)調(diào)用它們的析構(gòu)函數(shù)來(lái)清理該自定義類(lèi)型的成員變量。

倘若該自定義類(lèi)型成員同樣只有系統(tǒng)默認(rèn)生成的的析構(gòu)函數(shù),那么結(jié)果就相當(dāng)于該自定義類(lèi)型成員也沒(méi)有被銷(xiāo)毀。

不釋放內(nèi)置類(lèi)型的成員也是有一定道理的,防止釋放一些文件指針等等可能導(dǎo)致程序崩潰。

3. 拷貝構(gòu)函數(shù)

除了初始化和銷(xiāo)毀工作以外,最常見(jiàn)的就是將一個(gè)對(duì)象賦值、傳參等就必須要拷貝對(duì)象。而類(lèi)這種復(fù)雜類(lèi)型直接賦值是不起作用的,拷貝對(duì)象的操作要由拷貝構(gòu)造函數(shù)實(shí)現(xiàn),每次復(fù)制對(duì)象都要調(diào)用拷貝構(gòu)造函數(shù)。

3.1 拷貝構(gòu)造函數(shù)的定義

根據(jù)需求我們也可以猜測(cè)出C++中的拷貝構(gòu)造函數(shù)的設(shè)計(jì)。

拷貝構(gòu)造函數(shù)也是特殊的成員函數(shù),負(fù)責(zé)對(duì)象的拷貝賦值工作,這個(gè)操作只能發(fā)生在對(duì)象實(shí)例化的時(shí)候,拷貝構(gòu)造的本質(zhì)就是用同類(lèi)型的對(duì)象初始化新對(duì)象,所以也算是一種不同形式的構(gòu)造函數(shù)滿(mǎn)足重載的要求,也可叫復(fù)制構(gòu)造函數(shù)。

拷貝構(gòu)造函數(shù)僅有一個(gè)參數(shù),就是同類(lèi)型的對(duì)象的引用,在用同類(lèi)型的對(duì)象初始化新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用??截悩?gòu)造函數(shù)也是構(gòu)造函數(shù),所以拷貝也是構(gòu)造的一個(gè)重載。

3.2 拷貝構(gòu)造函數(shù)的特性

  • 拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個(gè)重載形式。
  • 拷貝構(gòu)造函數(shù)只有一個(gè)參數(shù),且必須是同類(lèi)型的對(duì)象的引用,否則會(huì)引發(fā)無(wú)窮遞歸。

因?yàn)閭髦嫡{(diào)用就要復(fù)制一份對(duì)象的臨時(shí)拷貝,而要想拷貝對(duì)象就必須要調(diào)用拷貝構(gòu)造函數(shù),而調(diào)用拷貝構(gòu)造函數(shù)又要傳值調(diào)用,這樣就會(huì)在調(diào)用參數(shù)列表中“邏輯死循環(huán)”出不來(lái)了。

設(shè)計(jì)拷貝構(gòu)造函數(shù)時(shí)就已經(jīng)修改了系統(tǒng)默認(rèn)生成的拷貝構(gòu)造函數(shù),所以在此過(guò)程不可以再發(fā)生拷貝操作。而傳引用不會(huì)涉及到拷貝操作所以沒(méi)問(wèn)題。

另外,有趣的是設(shè)計(jì)者規(guī)定拷貝構(gòu)造函數(shù)的參數(shù)必須是同類(lèi)型的引用,如果設(shè)計(jì)成指針,系統(tǒng)就當(dāng)作沒(méi)有顯式定義拷貝構(gòu)造函數(shù)了。

一般拷貝構(gòu)造另一個(gè)對(duì)象時(shí),都不希望原對(duì)象發(fā)生改變,所以形參引用用const修飾。

只顯式定義拷貝構(gòu)造函數(shù),系統(tǒng)不會(huì)生成默認(rèn)的構(gòu)造函數(shù),只定義構(gòu)造函數(shù),系統(tǒng)會(huì)默認(rèn)生成拷貝構(gòu)造。

默認(rèn)拷貝構(gòu)造拷貝規(guī)則

若未顯式定義拷貝構(gòu)造,和構(gòu)造函數(shù)類(lèi)似,默認(rèn)生成的拷貝構(gòu)造函數(shù)對(duì)成員的拷貝分兩種:

  • 對(duì)于內(nèi)置類(lèi)型的成員變量,默認(rèn)生成的拷貝構(gòu)造是把該成員的存儲(chǔ)內(nèi)容按字節(jié)序的順序逐字節(jié)拷貝至新對(duì)象中的。這樣的拷貝被稱(chēng)為淺拷貝或稱(chēng)值拷貝。類(lèi)似與memcopy函數(shù)。
  • 對(duì)于自定義類(lèi)型的成員,默認(rèn)生成的拷貝構(gòu)造函數(shù)是調(diào)用該自定義類(lèi)型成員的拷貝構(gòu)造函數(shù)進(jìn)行拷貝的。

默認(rèn)生成的拷貝函數(shù)也不是萬(wàn)能的,比如棧這個(gè)結(jié)構(gòu)。用st1初始化st2時(shí),會(huì)導(dǎo)致二者的成員_a指向相同的一塊空間。

4. 運(yùn)算符重載

運(yùn)算符重載是C++的一大利器,使得對(duì)象也可以用加減乘除等各種運(yùn)算符來(lái)進(jìn)行相加相減比較大小等有意義的運(yùn)算。默認(rèn)情況下C++不支持自定義類(lèi)型像內(nèi)置類(lèi)型變量一樣使用運(yùn)算符的,這里的規(guī)則需要開(kāi)發(fā)者通過(guò)運(yùn)算符重載函數(shù)來(lái)定義。

4.1 運(yùn)算符重載的定義

運(yùn)算符重載增強(qiáng)了代碼的可讀性也更方便,但為此我們必須要為類(lèi)對(duì)象編寫(xiě)運(yùn)算符重載函數(shù)以實(shí)現(xiàn)這樣操作。運(yùn)算符重載是具有特殊函數(shù)名的函數(shù),也具有返回類(lèi)型、函數(shù)名和參數(shù)列表。重載函數(shù)實(shí)現(xiàn)后由編譯器自動(dòng)識(shí)別和調(diào)用。

  1. 函數(shù)名是關(guān)鍵字operator加需要重載的運(yùn)算符符號(hào),如operator+,operator=等。
  2. 返回類(lèi)型和參數(shù)都要根據(jù)運(yùn)算符的規(guī)則和含義的實(shí)際情況來(lái)定。
bool operator>(const Date& d1, const Date& d2) {
	if (d1._year > d2._year) {
		return true;
	}
	else if (d1._year == d2._year && d1._month > d2._month) {
		return true;
	}
	else if (d1._year == d2._year && d1._month == d2._month && d1._day > d2._day) {
		return true;
	}
	return false;
}
d1 > d2;
operator>(d1, d2);

兩個(gè)日期類(lèi)進(jìn)行比較大小,傳參采用對(duì)象的常引用形式,避免調(diào)用拷貝構(gòu)造函數(shù)和改變實(shí)參,返回類(lèi)型為布爾值,同樣都是符合實(shí)際的。編譯器把operator>(d1,d2)轉(zhuǎn)換成d1>d2,大大提高了代碼的可讀性。

4.2 運(yùn)算符重載的特性

  • 只能重載已有的運(yùn)算符,不能通過(guò)連接其他符號(hào)來(lái)定義新的運(yùn)算,如operator@。
  • 重載操作符函數(shù)只能作用于自定義類(lèi)型對(duì)象,且最多有兩個(gè)參數(shù),自定義類(lèi)型最好采用常引用傳參。
  • 重載內(nèi)置類(lèi)型的操作符,建議不改變?cè)摬僮鞣旧砗x。
  • 共有5個(gè)運(yùn)算符不可被重載,分別是:.*,域訪問(wèn)操作符::,sizeof,三目運(yùn)算符?:,結(jié)構(gòu)成員訪問(wèn)符.。

運(yùn)算符重載不像構(gòu)造函數(shù)是固定在類(lèi)中的特殊的成員函數(shù),運(yùn)算符重載適用于所有自定義類(lèi)型對(duì)象,并不單獨(dú)局限于某個(gè)類(lèi)。但由于類(lèi)中的成員變量是私有的,運(yùn)算符重載想使其作用于某個(gè)類(lèi)時(shí),解決方法有三:

  1. 修改成員變量的訪問(wèn)權(quán)限變成公有,但破壞了類(lèi)的封裝性,是最不可取的。使用友元函數(shù),但性質(zhì)與修改訪問(wèn)權(quán)限類(lèi)似,同樣不可取的。
  2. 使用Getter Setter方法提供成員變量的接口,保留封裝性但較為麻煩。
  3. 將運(yùn)算符重載函數(shù)放到類(lèi)中變成成員函數(shù),但需要注意修改一些細(xì)節(jié)。作為類(lèi)成員的重載函數(shù),形參列表默認(rèn)隱藏 this 指針,所以必須去掉一個(gè)引用參數(shù)。
class Date {
public:
	Date(int year = 0, int month = 1, int day = 1);
	bool operator>(const Date& d);
private:
	int _year;
	int _month;
	int _day;
};
//bool Date::operator>(Date* this, const Date& d) {...}
bool Date::operator>(const Date& d) {
	// ...
}
d1 > d2;
d1.operator>(d2); //成員函數(shù)只能這樣調(diào)用

4.3 賦值運(yùn)算符重載

賦值運(yùn)算符重載實(shí)現(xiàn)的是兩個(gè)自定義類(lèi)型的對(duì)象的賦值,和拷貝構(gòu)造函數(shù)不同拷貝構(gòu)造是用一個(gè)已存在的對(duì)象去初始化一個(gè)對(duì)象,賦值運(yùn)算符重載是兩個(gè)已存在的對(duì)象進(jìn)行賦值操作。和兩個(gè)整形數(shù)據(jù)的賦值意義相同,所以定義時(shí)也是參考內(nèi)置類(lèi)型的賦值操作來(lái)的。

  • 參數(shù)列表 —— 兩個(gè)對(duì)象進(jìn)行賦值操作,由于放在類(lèi)中作成員函數(shù),參數(shù)列表僅顯式定義一個(gè)對(duì)象的引用。
  • 返回類(lèi)型 —— 賦值表達(dá)式的返回值也是操作數(shù)的值,返回對(duì)象的引用即可。
// i = j = k = 1;
Date& Date::operator=(const Date& d) {
	if (this != &d) { //優(yōu)化自己給自己賦值
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}

不傳參對(duì)象的引用或者不返回對(duì)象的引用都會(huì)調(diào)用拷貝構(gòu)造函數(shù),為使減少拷貝和避免修改原對(duì)象,最好使用常引用。

默認(rèn)賦值重載賦值規(guī)則

類(lèi)中如果沒(méi)有顯式的定義賦值重載函數(shù),編譯器會(huì)在類(lèi)中默認(rèn)生成一個(gè)賦值重載函數(shù)的成員函數(shù)。默認(rèn)賦值重載對(duì)于內(nèi)置類(lèi)型的成員采用淺拷貝的方式拷貝,對(duì)于自定義類(lèi)型的成員會(huì)調(diào)用它內(nèi)部的賦值重載函數(shù)進(jìn)行賦值。

所以寫(xiě)不寫(xiě)賦值重載仍然要視情況而定。

Date d5 = d1;
// 用已存在的對(duì)象初始化新對(duì)象,則是拷貝構(gòu)造而非賦值重載

掌握以上四種C++中默認(rèn)的函數(shù),就可以實(shí)現(xiàn)完整的日期類(lèi)了。

5. 日期類(lèi)的實(shí)現(xiàn)

5.1 日期類(lèi)的定義

class Date {
public:
	Date(int year = 0, int month = 1, int day = 1);
	Date(const Date& d);
	~Date();
    void Print();
	int GetMonthDay();

    bool operator>(const Date& d);
	bool operator<(const Date& d);
	bool operator>=(const Date& d);
	bool operator<=(const Date& d);
	bool operator==(const Date& d);
	bool operator!=(const Date& d);

	Date& operator=(const Date& d);

	Date& operator+=(int day);
	Date operator+(int day);
	Date& operator-=(int day);
	int operator-(const Date& d);
	Date operator-(int day);

	Date& operator++();
	Date operator++(int);
	Date& operator--();
	Date operator--(int);
private:
	int _year;
	int _month;
	int _day;
};

日期類(lèi)很簡(jiǎn)單,一樣的函數(shù)一樣的變量再封裝起來(lái),把之前聯(lián)系的代碼放到一起。接下來(lái)就是函數(shù)接口的具體實(shí)現(xiàn)細(xì)節(jié)了。

5.2 日期類(lèi)的接口實(shí)現(xiàn)

//構(gòu)造函數(shù)
Date(int year = 0, int month = 1, int day = 1);
//打印
void Print();
//拷貝構(gòu)造
Date(const Date& d);
//析構(gòu)函數(shù)
~Date();
//獲取當(dāng)月天數(shù)
int GetMonthDay();
// >運(yùn)算符重載
bool operator>(const Date& d);
// >=運(yùn)算符重載
bool operator>=(const Date& d);
// <運(yùn)算符重載
bool operator<(const Date& d);
// <=運(yùn)算符重載
bool operator<=(const Date& d);
// ==運(yùn)算符重載
bool operator==(const Date& d);
// !=運(yùn)算符重載
bool operator!=(const Date& d);
// =運(yùn)算符重載
Date& operator=(const Date& d);
//日期+天數(shù)=日期
Date& operator+=(int day);
//日期+天數(shù)=日期
Date operator+(int day);
//日期-天數(shù)=日期
Date& operator-=(int day);
//日期-日期=天數(shù)  
int operator-(const Date& d);
//日期-天數(shù)=日期
Date operator-(int day);
//前置++
Date& operator++();
//后置++
Date operator++(int);
//前置--
Date& operator--();
//后置--
Date operator--(int);

從上述函數(shù)聲明的列表也可以看出,構(gòu)造函數(shù)、析構(gòu)函數(shù)等都是相對(duì)簡(jiǎn)單的,實(shí)現(xiàn)類(lèi)的重點(diǎn)同樣也是難點(diǎn)是定義各種運(yùn)算符的重載。

日期類(lèi)的構(gòu)造函數(shù)

日期類(lèi)的構(gòu)造函數(shù)之前實(shí)現(xiàn)過(guò),但仍需注意一些細(xì)節(jié),比如過(guò)濾掉一些不合法的日期。要想實(shí)現(xiàn)這個(gè)功能就要定好每年每月的最大合法天數(shù),可以將其存儲(chǔ)在數(shù)組MonthDayArray,并封裝在函數(shù)GetMonthDay中以便在判斷的時(shí)候調(diào)用。

//獲取合法天數(shù)的最大值
int Date::GetMonthDay() {
	static int MonthDayArray[13] = { 0, 31 ,28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	int day = MonthDayArray[_month];
	//判斷閏年
	if (_month == 2 && ((_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0))) {
		day += 1;
	}
	return day;
}
//構(gòu)造函數(shù)
Date::Date(int year, int month, int day) {
	_year = year;
	_month = month;
	_day = day;
	//判斷日期是否合法
	if (month > 12 || day > GetMonthDay()) {
		cout << "請(qǐng)檢查日期是否合法:";
		Print();
	}
}

數(shù)組MonthDayArray的定義也有講究,定義13個(gè)數(shù)組元素,第一個(gè)元素就放0,這樣讓數(shù)組下標(biāo)和月份對(duì)應(yīng)起來(lái),使用更加方便。確定每月的天數(shù)還要看年份是否是閏年,所以還要判斷是否是閏年,因?yàn)殚c年的二月都要多一天。這些封裝在函數(shù)GetMonthDay中,調(diào)用時(shí)返回當(dāng)月具體天數(shù),放在構(gòu)造函數(shù)中判斷是否日期是否合法。

由于兩個(gè)函數(shù)都是定義在類(lèi)中的,默認(rèn)將類(lèi)對(duì)象的指針作函數(shù)參數(shù),調(diào)用時(shí)更加方便。

析構(gòu)函數(shù)、打印函數(shù)和拷貝構(gòu)造函數(shù)都很簡(jiǎn)單和之前一樣,這里就不寫(xiě)了。接下來(lái)就是實(shí)現(xiàn)的重點(diǎn)運(yùn)算符重載。

比較運(yùn)算符的重載

//運(yùn)算符重載 >
bool Date::operator>(const Date& d) {
	if (_year > d._year) {
		return true;
	}
	else if (_year == d._year && _month > d._month) {
		return true;
	}
	else if (_year == d._year && _month == d._month && _day > d._day) {
		return true;
	}
	return false;
}
//運(yùn)算符重載 >=
bool Date::operator>=(const Date & d) {
	return (*this > d) || (*this == d);
}
//運(yùn)算符重載 <
bool Date::operator<(const Date& d) {
	return !(*this >= d);
}
//運(yùn)算符重載 <=
bool Date::operator<=(const Date& d) {
	return !(*this > d);
}
//運(yùn)算符重載 ==
bool Date::operator==(const Date& d) {
	return (_year == d._year) && (_month == d._month) && (_day == d._day);
}
//運(yùn)算符重載 !=
bool Date::operator!=(const Date& d) {
	return !(*this == d);
}

比較運(yùn)算符的重載不難實(shí)現(xiàn),注意代碼的邏輯即可。主要實(shí)現(xiàn)>和==的重載,其他的都調(diào)用這兩個(gè)函數(shù)就行。這樣的實(shí)現(xiàn)方法基本適用所有的類(lèi)。

加法運(yùn)算符的重載

加法實(shí)現(xiàn)的意義在于實(shí)現(xiàn)日期+天數(shù)=日期的運(yùn)算,可以現(xiàn)在稿紙上演算一下探尋一下規(guī)律。

可以看出加法的規(guī)律是,先將天數(shù)加到天數(shù)位上,然后判斷天數(shù)是否合法。

  1. 如果不合法則要減去當(dāng)月的最大合法天數(shù)值,相當(dāng)于進(jìn)到下一月,即先減值再進(jìn)位。
  2. 若天數(shù)合法,則進(jìn)位運(yùn)算結(jié)束。
  3. 在天數(shù)進(jìn)位的同時(shí),月數(shù)如果等于13則賦值為1,再年份加1,可將剩余天數(shù)同步到明年。

先減值再進(jìn)位的原因是,減值所減的是當(dāng)月的最大合法天數(shù),若先進(jìn)位的話(huà),修改了月份則會(huì)減成下個(gè)月的天數(shù)。

//運(yùn)算符重載 +=
//日期 + 天數(shù) = 日期 
Date& Date::operator+=(int day) {
	_day += day;
	//檢查天數(shù)是否合法
	while (_day > GetMonthDay()) {
		_day -= GetMonthDay();//天數(shù)減合法最大值 --- 先減值,再進(jìn)位
		_month++;//月份進(jìn)位
		//檢查月數(shù)是否合法
        if (_month == 13) { 
			_month = 1;
			_year += 1;//年份進(jìn)位
		}
	}
	return *this;
}

這樣的實(shí)現(xiàn)方法會(huì)改變對(duì)象的值,不如直接將其實(shí)現(xiàn)為+=,并返回對(duì)象的引用還可以避免調(diào)用拷貝構(gòu)造。

實(shí)現(xiàn)+重載再去復(fù)用+=即可。

//運(yùn)算符重載 +
Date Date::operator+(int day) {//臨時(shí)變量會(huì)銷(xiāo)毀,不可傳引用
	Date ret(*this);
	ret += day; // ret.operator+=(day);
	return ret;
}

創(chuàng)建臨時(shí)變量并用*this初始化,再使用臨時(shí)變量進(jìn)行+=運(yùn)算,返回臨時(shí)變量即可。注意臨時(shí)變量隨棧幀銷(xiāo)毀,不可返回它的引用。

減法運(yùn)算符的重載

//運(yùn)算符重載 -=
//日期 - 天數(shù) = 日期
Date& Date::operator-=(int day) {
    //防止天數(shù)是負(fù)數(shù)
	if (_day < 0) {
		return *this += -day;
	}
	_day -= day;
	//檢查天數(shù)是否合法
	while (_day <= 0) {
		_month--;//月份借位
		//檢查月份是否合法
		if (_month == 0) {
			_month = 12;
			_year--;//年份借位
		}
		_day += GetMonthDay();//天數(shù)加上合法最大值 --- 先借位,再加值
	}
	return *this;
}

實(shí)現(xiàn)減法邏輯和加法類(lèi)似,先將天數(shù)減到天數(shù)位上,再檢查天數(shù)是否合法:

  1. 如果天數(shù)不合法,向月份借位,再加上上月的最大合法天數(shù),即先借位再加值。并檢查月份是否合法,月份若為0則置為12年份再借位。
  2. 如果天數(shù)合法,則停止借位。

先借位再加值是因?yàn)榧又迪喈?dāng)于去掉上個(gè)月的過(guò)的天數(shù),所以應(yīng)加上的是上月的天數(shù)。

值得注意的是,修正月數(shù)的操作必須放在加值的前面,因?yàn)楫?dāng)月數(shù)借位到0時(shí),必須要修正才能正常加值。

//運(yùn)算符重載 -
//日期 - 天數(shù) = 日期
Date Date::operator-(int day) {
	Date ret(*this);
	ret -= day;
	return ret;
}
//日期 - 日期 = 天數(shù)  
int Date::operator-(const Date& d) {
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (max < min) {
		max = d;
		min = *this;
		flag = -1;
	}
	int gap = 0;
	while ((min + gap) != max) {
		gap++;
	}
	return gap * flag;
}

日期-日期=天數(shù)的計(jì)算可以稍微轉(zhuǎn)化一下變成日期+天數(shù)=日期,讓小的日期加上一個(gè)逐次增加的值所得結(jié)果和大的日期相等,那么這個(gè)值就是二者所差的天數(shù)。

加的時(shí)候,日期不合法是因?yàn)樘鞌?shù)已經(jīng)超出了當(dāng)月的最大合法天數(shù),既然超出了,就將多余的部分留下,把當(dāng)月最大合法天數(shù)減去以增加月數(shù)。減的時(shí)候同理,日期不合法是因?yàn)樘鞌?shù)已經(jīng)低于了0,回到了上一個(gè)月,那就補(bǔ)全上一個(gè)月的最大合法數(shù)值用此去加上這個(gè)負(fù)數(shù),這個(gè)負(fù)數(shù)就相當(dāng)于此月沒(méi)有過(guò)完的剩余的天數(shù)。

自增自減的重載

C++為區(qū)分前置和后置,規(guī)定后置自增自減的重載函數(shù)參數(shù)要顯式傳一個(gè)int參數(shù)占位,可以和前置構(gòu)成重載。

//前置++
Date& Date::operator++() {
	return *this += 1;
}
//后置++
Date Date::operator++(int) {
	return (*this += 1) - 1;
}
//前置--
Date& Date::operator--() {
	return *this -= 1;
}
//后置--
Date Date::operator--(int) {
	return (*this -= 1) + 1;
}
// 實(shí)現(xiàn)方式2
Date ret = *this;
*this + 1;
return ret;

實(shí)現(xiàn)對(duì)象的前置后置的自增和自減,要滿(mǎn)足前置先運(yùn)算再使用和后置先使用再運(yùn)算的特性。也用上面實(shí)現(xiàn)好的重載復(fù)用即可?;蛘咭部梢灾苯永门R時(shí)變量保存*this,改變*this之后返回臨時(shí)變量即可。

++d2;
d2.operator();
d1++;
d1.operator(0);

可以看出,對(duì)于類(lèi)對(duì)象來(lái)說(shuō),前置++比后置++快不少,只調(diào)用了一次析構(gòu)函數(shù),而后置++ 調(diào)用了兩次拷貝構(gòu)造和三次析構(gòu)。

6. const 類(lèi)

被const修飾的類(lèi)即為 const 類(lèi),const 類(lèi)調(diào)用成員函數(shù)時(shí)出錯(cuò),因?yàn)閰?shù)this指針從const Date*到Date*涉及權(quán)限放大的問(wèn)題。如圖所示:

6.1 const 類(lèi)的成員函數(shù)

想要避免這樣的問(wèn)題,就必須修改成員函數(shù)的形參this,但 this 指針不能被顯式作參數(shù)自然不可被修改。為解決這樣的問(wèn)題,C++規(guī)定在函數(shù)聲明后面加上 const ,就相當(dāng)于給形參 this 指針添加 const 修飾。

//運(yùn)算符重載 !=
//聲明
bool Date::operator!=(const Date& d) const;
//定義
bool Date::operator!=(const Date& d) const {
	return !(*this == d);
}

像上述代碼這樣,由 const 修飾的類(lèi)成員函數(shù)稱(chēng)之為 const 成員函數(shù),const 修飾類(lèi)成員函數(shù),實(shí)際修飾函數(shù)的隱含形參 this 指針,這樣該函數(shù)就不可修改對(duì)象的成員變量。

6.2 取地址操作符重載

還有兩個(gè)類(lèi)的默認(rèn)成員函數(shù),取地址操作符重載和 const 取地址操作符重載,這兩個(gè)默認(rèn)成員函數(shù)一般不用定義,編譯器默認(rèn)生成的就夠用了。

Date* operator&() {
    return this;
    //return NULL; //不允許獲取對(duì)象的地址
}
const Date* operator&() const {
    return this;
}

當(dāng)不允許獲取對(duì)象的地址時(shí),就可以將取地址重載成空即可。

總結(jié)

到此這篇關(guān)于C++初階教程之類(lèi)和對(duì)象的文章就介紹到這了,更多相關(guān)C++類(lèi)和對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++索引越界的解決方法

    C++索引越界的解決方法

    本文主要介紹了C++索引越界的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++中的基類(lèi)和派生類(lèi)構(gòu)造函數(shù)示例詳解

    C++中的基類(lèi)和派生類(lèi)構(gòu)造函數(shù)示例詳解

    這篇文章主要介紹了C++的基類(lèi)和派生類(lèi)構(gòu)造函數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • C語(yǔ)言實(shí)現(xiàn)的猜數(shù)字小游戲

    C語(yǔ)言實(shí)現(xiàn)的猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)的猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • c++入門(mén)必學(xué)庫(kù)函數(shù)sort的基本用法

    c++入門(mén)必學(xué)庫(kù)函數(shù)sort的基本用法

    Sort函數(shù)包含在頭文件為#include<algorithm>的c++標(biāo)準(zhǔn)庫(kù)中,調(diào)用標(biāo)準(zhǔn)庫(kù)里的排序方法可以不必知道其內(nèi)部是如何實(shí)現(xiàn)的,只要出現(xiàn)我們想要的結(jié)果即可,下面這篇文章主要給大家介紹了關(guān)于c++入門(mén)必學(xué)庫(kù)函數(shù)sort的基本用法,需要的朋友可以參考下
    2022-11-11
  • 基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的五子棋游戲

    基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C語(yǔ)言單鏈表實(shí)現(xiàn)通訊錄管理系統(tǒng)

    C語(yǔ)言單鏈表實(shí)現(xiàn)通訊錄管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言單鏈表實(shí)現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • C語(yǔ)言進(jìn)階教程之字符串&內(nèi)存函數(shù)

    C語(yǔ)言進(jìn)階教程之字符串&內(nèi)存函數(shù)

    對(duì)于字符,在計(jì)算機(jī)內(nèi)部都是用數(shù)字(字符編碼)來(lái)表示的,而字符串是“字符連續(xù)排列”的一種表現(xiàn),這篇文章主要給大家介紹了關(guān)于C語(yǔ)言進(jìn)階教程之字符串&內(nèi)存函數(shù)的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • linux c程序中獲取shell腳本輸出的實(shí)現(xiàn)方法

    linux c程序中獲取shell腳本輸出的實(shí)現(xiàn)方法

    以下是對(duì)在linux下c程序中獲取shell腳本輸出的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • C++?Qt實(shí)現(xiàn)一個(gè)解除文件占用小工具

    C++?Qt實(shí)現(xiàn)一個(gè)解除文件占用小工具

    這篇文章主要為大家詳細(xì)介紹了如何利用C++?Qt實(shí)現(xiàn)一個(gè)解除文件占用小工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • C語(yǔ)言深入講解之從函數(shù)棧幀角度理解return關(guān)鍵字

    C語(yǔ)言深入講解之從函數(shù)棧幀角度理解return關(guān)鍵字

    在C語(yǔ)言中,一般情況下函數(shù)的返回值是通過(guò)函數(shù)中的return語(yǔ)句來(lái)實(shí)現(xiàn)的,每調(diào)用一次return語(yǔ)句只能從函數(shù)中返回一個(gè)值,這篇文章主要給大家介紹了關(guān)于C語(yǔ)言從函數(shù)棧幀角度理解return關(guān)鍵字的相關(guān)資料,需要的朋友可以參考下
    2021-09-09

最新評(píng)論

红河县| 望谟县| 玉溪市| 双牌县| 巴马| 博兴县| 宿州市| 邓州市| 墨脱县| 镇宁| 贵德县| 教育| 仁怀市| 阿拉尔市| 云安县| 松原市| 阿克苏市| 海南省| 邹平县| 康乐县| 湘乡市| 大石桥市| 兰州市| 浠水县| 遵化市| 阳江市| 台南县| 临沭县| 洱源县| 武平县| 绥江县| 穆棱市| 黄冈市| 蒲江县| 保定市| 盘锦市| 永修县| 玉溪市| 金昌市| 云林县| 怀柔区|