GeekBand C++ 第一周

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


構(gòu)造函數(shù)名稱=類名。構(gòu)造函數(shù)的作用:初始化對象的數(shù)據(jù)成員。

1.1 構(gòu)造函數(shù)的種類

引自:http://www.cnblogs.com/xkfz007/archive/2012/05/11/2496447.html

class Complex

{

private :

double? ? m_real;

double? ? m_imag;

public:

//? ? 無參數(shù)構(gòu)造函數(shù)

// 如果創(chuàng)建一個類你沒有寫任何構(gòu)造函數(shù),則系統(tǒng)會自動生成默認的無參構(gòu)造函數(shù),函數(shù)為空,什么都不做

// 只要你寫了一個下面的某一種構(gòu)造函數(shù),系統(tǒng)就不會再自動生成這樣一個默認的構(gòu)造函數(shù),如果希望有一個這樣的無參構(gòu)造函數(shù),則需要自己顯示地寫出來

Complex(void)

{

m_real = 0.0;

m_imag = 0.0;

}

//? ? 一般構(gòu)造函數(shù)(也稱重載構(gòu)造函數(shù))

// 一般構(gòu)造函數(shù)可以有各種參數(shù)形式,一個類可以有多個一般構(gòu)造函數(shù),前提是參數(shù)的個數(shù)或者類型不同(基于c++的重載函數(shù)原理)

// 例如:你還可以寫一個 Complex( int num)的構(gòu)造函數(shù)出來

// 創(chuàng)建對象時根據(jù)傳入的參數(shù)不同調(diào)用不同的構(gòu)造函數(shù)

Complex(double real, double imag)

{

m_real = real;

m_imag = imag;

}

//? ? 復(fù)制構(gòu)造函數(shù)(也稱為拷貝構(gòu)造函數(shù))

//? ? 復(fù)制構(gòu)造函數(shù)參數(shù)為類對象本身的引用,用于根據(jù)一個已存在的對象復(fù)制出一個新的該類的對象,一般在函數(shù)中會將已存在對象的數(shù)據(jù)成員的值復(fù)制一份到新創(chuàng)建的對象中

//? ? 若沒有顯示的寫復(fù)制構(gòu)造函數(shù),則系統(tǒng)會默認創(chuàng)建一個復(fù)制構(gòu)造函數(shù),但當類中有指針成員時,由系統(tǒng)默認創(chuàng)建該復(fù)制構(gòu)造函數(shù)會存在風險,具體原因請查詢 有關(guān) “淺拷貝” 、“深拷貝”的文章論述

Complex(const Complex & c)

{

// 將對象c中的數(shù)據(jù)成員值復(fù)制過來

m_real = c.m_real;

m_imag? ? = c.m_imag;

}

// 類型轉(zhuǎn)換構(gòu)造函數(shù),根據(jù)一個指定的類型的對象創(chuàng)建一個本類的對象,

//需要注意的一點是,這個其實就是一般的構(gòu)造函數(shù),但是對于出現(xiàn)這種單參數(shù)的構(gòu)造函數(shù),C++會默認將參數(shù)對應(yīng)的類型轉(zhuǎn)換為該類類型,有時候這種隱私的轉(zhuǎn)換是我們所不想要的,所以需要使用explicit來限制這種轉(zhuǎn)換。

// 例如:下面將根據(jù)一個double類型的對象創(chuàng)建了一個Complex對象

Complex(double r)

{

m_real = r;

m_imag = 0.0;

}

// 等號運算符重載(也叫賦值構(gòu)造函數(shù))

// 注意,這個類似復(fù)制構(gòu)造函數(shù),將=右邊的本類對象的值復(fù)制給等號左邊的對象,它不屬于構(gòu)造函數(shù),等號左右兩邊的對象必須已經(jīng)被創(chuàng)建

// 若沒有顯示的寫=運算符重載,則系統(tǒng)也會創(chuàng)建一個默認的=運算符重載,只做一些基本的拷貝工作

Complex &operator=( const Complex &rhs )

{

// 首先檢測等號右邊的是否就是左邊的對象本身,若是本對象本身,則直接返回

if ( this == &rhs )

{

return *this;

}

// 復(fù)制等號右邊的成員到左邊的對象中

this->m_real = rhs.m_real;

this->m_imag = rhs.m_imag;

// 把等號左邊的對象再次傳出

// 目的是為了支持連等 eg:? ? a=b=c 系統(tǒng)首先運行 b=c

// 然后運行 a= ( b=c的返回值,這里應(yīng)該是復(fù)制c值后的b對象)

return *this;

}

};

下面使用上面定義的類對象來說明各個構(gòu)造函數(shù)的用法:

int main()

{

// 調(diào)用了無參構(gòu)造函數(shù),數(shù)據(jù)成員初值被賦為0.0

Complex c1,c2;

// 調(diào)用一般構(gòu)造函數(shù),數(shù)據(jù)成員初值被賦為指定值

Complex c3(1.0,2.5);

// 也可以使用下面的形式

Complex c3 = Complex(1.0,2.5);

//? ? 把c3的數(shù)據(jù)成員的值賦值給c1

//? ? 由于c1已經(jīng)事先被創(chuàng)建,故此處不會調(diào)用任何構(gòu)造函數(shù)

//? ? 只會調(diào)用 = 號運算符重載函數(shù)

c1 = c3;

//? ? 調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù)

//? ? 系統(tǒng)首先調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù),將5.2創(chuàng)建為一個本類的臨時對象,然后調(diào)用等號運算符重載,將該臨時對象賦值給c1

c2 = 5.2;

// 調(diào)用拷貝構(gòu)造函數(shù)( 有下面兩種調(diào)用方式)

Complex c5(c2);

Complex c4 = c2;? // 注意和 = 運算符重載區(qū)分,這里等號左邊的對象不是事先已經(jīng)創(chuàng)建,故需要調(diào)用拷貝構(gòu)造函數(shù),參數(shù)為c2

//這一點特別重要,這兒是初始化,不是賦值。其實這兒就涉及了C++中的兩種初始化的方式:復(fù)制初始化和賦值初始化。其中c5采用的是復(fù)制初始化,而c4采用的是賦值初始化,這兩種方式都是要調(diào)用拷貝構(gòu)造函數(shù)的。

}

1.2隨堂筆記

構(gòu)造函數(shù)都有initialization list(初始化列表),寫代碼時應(yīng)充分利用初始化列表,使用初始化列表比在函數(shù)體內(nèi)初始化成員變量效率高。

函數(shù)可以overloading(重載),允許同名函數(shù),但是實參不能一樣,但是在編譯后的名稱實際是不一樣的,不存在編譯后名稱一樣的兩個函數(shù)。函數(shù)重載常常發(fā)生在構(gòu)造函數(shù)。

已有一個構(gòu)造函數(shù),實參均有默認值,則不能再寫一個無參數(shù)構(gòu)造函數(shù)。兩者均可為默認構(gòu)造函數(shù),實際上有沖突。

constructor放在private區(qū)域: singleton 單例模式

2.C++運算符重載

2.1C++運算符重載

引自:http://blog.csdn.net/zgl_dm/article/details/1767201

C++中預(yù)定義的運算符的操作對象只能是基本數(shù)據(jù)類型。但實際上,對于許多用戶自定義類型(例如類),也需要類似的運算操作。這時就必須在C++中重新定義這些運算符,賦予已有運算符新的功能,使它能夠用于特定類型執(zhí)行特定的操作。運算符重載的實質(zhì)是函數(shù)重載,它提供了C++的可擴展性,也是C++最吸引人的特性之一。

運算符重載是通過創(chuàng)建運算符函數(shù)實現(xiàn)的,運算符函數(shù)定義了重載的運算符將要進行的操作。運算符函數(shù)的定義與其他函數(shù)的定義類似,惟一的區(qū)別是運算符函數(shù)的函數(shù)名是由關(guān)鍵字operator和其后要重載的運算符符號構(gòu)成的。運算符函數(shù)定義的一般格式如下:

<返回類型說明符>operator<運算符符號>(<參數(shù)表>)

{

<函數(shù)體>

}

運算符重載時要遵循以下規(guī)則:

(1)?除了類屬關(guān)系運算符"."、成員指針運算符".*"、作用域運算符"::"、sizeof運算符和三目運算符"?:"以外,C++中的所有運算符都可以重載。

(2)?重載運算符限制在C++語言中已有的運算符范圍內(nèi)的允許重載的運算符之中,不能創(chuàng)建新的運算符。

(3)?運算符重載實質(zhì)上是函數(shù)重載,因此編譯程序?qū)\算符重載的選擇,遵循函數(shù)重載的選擇原則。

(4)?重載之后的運算符不能改變運算符的優(yōu)先級和結(jié)合性,也不能改變運算符操作數(shù)的個數(shù)及語法結(jié)構(gòu)。

(5)?運算符重載不能改變該運算符用于內(nèi)部類型對象的含義。它只能和用戶自定義類型的對象一起使用,或者用于用戶自定義類型的對象和內(nèi)部類型的對象混合使用時。

(6)?運算符重載是針對新類型數(shù)據(jù)的實際需要對原有運算符進行的適當?shù)母脑?,重載的功能應(yīng)當與原有功能相類似,避免沒有目的地使用重載運算符。

運算符函數(shù)重載一般有兩種形式:重載為類的成員函數(shù)和重載為類的非成員函數(shù)。非成員函數(shù)通常是友元。(可以把一個運算符作為一個非成員、非友元函數(shù)重載。但是,這樣的運算符函數(shù)訪問類的私有和保護成員時,必須使用類的公有接口中提供的設(shè)置數(shù)據(jù)和讀取數(shù)據(jù)的函數(shù),調(diào)用這些函數(shù)時會降低性能??梢詢?nèi)聯(lián)這些函數(shù)以提高性能。)

成員函數(shù)運算符

運算符重載為類的成員函數(shù)的一般格式為:

<函數(shù)類型>operator<運算符>(<參數(shù)表>)

{

<函數(shù)體>

}

當運算符重載為類的成員函數(shù)時,函數(shù)的參數(shù)個數(shù)比原來的操作數(shù)要少一個(后置單目運算符除外),這是因為成員函數(shù)用this指針隱式地訪問了類的一個對象,它充當了運算符函數(shù)最左邊的操作數(shù)。因此:

(1)?雙目運算符重載為類的成員函數(shù)時,函數(shù)只顯式說明一個參數(shù),該形參是運算符的右操作數(shù)。

(2)?前置單目運算符重載為類的成員函數(shù)時,不需要顯式說明參數(shù),即函數(shù)沒有形參。

(3)?后置單目運算符重載為類的成員函數(shù)時,函數(shù)要帶有一個整型形參。

調(diào)用成員函數(shù)運算符的格式如下:

<對象名>.operator<運算符>(<參數(shù)>)

它等價于

<對象名><運算符><參數(shù)>

例如:a+b等價于a.operator+(b)。一般情況下,我們采用運算符的習慣表達方式。

友元函數(shù)運算符

運算符重載為類的友元函數(shù)的一般格式為:

friend<函數(shù)類型>operator<運算符>(<參數(shù)表>)

{

<函數(shù)體>

}

當運算符重載為類的友元函數(shù)時,由于沒有隱含的this指針,因此操作數(shù)的個數(shù)沒有變化,所有的操作數(shù)都必須通過函數(shù)的形參進行傳遞,函數(shù)的參數(shù)與操作數(shù)自左至右一一對應(yīng)。

調(diào)用友元函數(shù)運算符的格式如下:

operator<運算符>(<參數(shù)1>,<參數(shù)2>)

它等價于

<參數(shù)1><運算符><參數(shù)2>

例如:a+b等價于operator+(a,b)。

兩種重載形式的比較

在多數(shù)情況下,將運算符重載為類的成員函數(shù)和類的友元函數(shù)都是可以的。但成員函數(shù)運算符與友元函數(shù)運算符也具有各自的一些特點:

(1)?一般情況下,單目運算符最好重載為類的成員函數(shù);雙目運算符則最好重載為類的友元函數(shù)。

(2)?以下一些雙目運算符不能重載為類的友元函數(shù):=、()、[]、->。

(3)?類型轉(zhuǎn)換函數(shù)只能定義為一個類的成員函數(shù)而不能定義為類的友元函數(shù)。

(4)?若一個運算符的操作需要修改對象的狀態(tài),選擇重載為成員函數(shù)較好。

(5)?若運算符所需的操作數(shù)(尤其是第一個操作數(shù))希望有隱式類型轉(zhuǎn)換,則只能選用友元函數(shù)。

(6)?當運算符函數(shù)是一個成員函數(shù)時,最左邊的操作數(shù)(或者只有最左邊的操作數(shù))必須是運算符類的一 個類對象(或者是對該類對象的引用)。如果左邊的操作數(shù)必須是一個不同類的對象,或者是一個內(nèi)部 類型的對象,該運算符函數(shù)必須作為一個友元函數(shù)來實現(xiàn)。

(7)?當需要重載運算符具有可交換性時,選擇重載為友元函數(shù)。

2.2隨堂筆記

complex c1(2,1);

complex c2(5);

c2 += c1;

操作符作用在左邊的操作數(shù)上。

class的成員函數(shù)帶一個隱藏參數(shù),this指針,不能再代碼中體現(xiàn),this指針參數(shù)位置不一定是第一個,取決于編譯器。


為了滿足 c3 += c2 += c1;重載 += 時必須有返回值;

3.參數(shù)傳遞與返回值

const member functions 常量成員函數(shù)

對于class里面的函數(shù),分為會改變class內(nèi)數(shù)據(jù)內(nèi)容的和不會改變class內(nèi)數(shù)據(jù)內(nèi)容。

不會改變class內(nèi)數(shù)據(jù)內(nèi)容的函數(shù),馬上加上const。

參數(shù)傳遞 pass by value vs. pass by reference(to const)

傳reference底層就是傳指針,速度快,形式好看,如果不想被改變,則加上const。

返回值傳遞,pass by value vs. pass by reference(to const)

對于函數(shù)體內(nèi)創(chuàng)建的local object,不能return by reference,因為他的生命周期在函數(shù)返回后就終止了。此時若用reference返回,則會返回壞的內(nèi)容。

friend(友元函數(shù))

友元函數(shù)可以直接訪問class的private數(shù)據(jù)。

相同class的各個objects互為friends(友元)。

寫一個class應(yīng)該注意的地方。

1、數(shù)據(jù)一定放在private里面。

2、參數(shù)盡量以reference來傳遞,看情況加上const。

3、返回值盡量也以reference來傳遞,可以的情況下。

4、class內(nèi)的各種函數(shù),需要加const的一定要加上const。

5、構(gòu)造函數(shù)的初始化數(shù)據(jù)使用initialization list。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.constructor構(gòu)造函數(shù) 構(gòu)造函數(shù)名稱=類名。構(gòu)造函數(shù)的作用:初始化對象的數(shù)據(jù)成員。 1.1 構(gòu)造函數(shù)的...
    hui1429閱讀 435評論 0 0
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,655評論 1 51
  • ● 概述:以c++標準庫中的complex對象為例,介紹了成員無指針的類的基本寫法 ● c++的歷史○ 1.0:c...
    billow06閱讀 128評論 0 0
  • 這是一篇分享變美的干貨,也是我自己的一段很艱辛的抗痘路程! 2015年前遇見我的人對我的印像應(yīng)該是,個子小小的,性...
    一只小遠遠閱讀 587評論 0 1
  • 今年高二了,我發(fā)現(xiàn)班上的男生越來越討厭了,居然給我起了個外號叫女包公!一見到我就大唱“開封有個包青天……” 真是的...
    護膚001閱讀 314評論 0 0

友情鏈接更多精彩內(nèi)容