C++學習小結

來源:互聯網
上載者:User

一、構造和解構函式

C++在幕後為你寫的的函數:一個拷貝建構函式,一個賦值運算子,一個解構函式,一對取址運算子。另外,如果你沒有聲明任何建構函式,它也將為你聲明一個預設建構函式。所有這些函數都是公有的。換句話說,如果你這麼寫:

class Empty{};

和你這麼寫是一樣的:

class Empty {public:  Empty();                        // 預設建構函式  Empty(const Empty& rhs);        // 拷貝建構函式  ~Empty();                       // 解構函式 ---- 是否為虛函數看下文說明  Empty&  operator=(const Empty& rhs);    // 賦值運算子  Empty* operator&();             // 取址運算子  const Empty* operator&() const;};

深拷貝和淺拷貝:

預設拷貝建構函式均是淺拷貝。但是一個類可能擁有其它資源,如其建構函式分配了一個堆記憶體,解構函式釋放了這個記憶體,則此時就需要進行深拷貝了,深拷貝不能依賴編譯器實現。為需要動態分配記憶體的類聲明一個拷貝建構函式和一個賦值操作符。

拷貝建構函式的調用:
1、當用類的一個對象去初始化該類的另一個對象時。
2、當對象作為函數的實參傳遞給函數的形參時。
3、當函數的傳回值是類的對象,函數執行完成返回時。

在建構函式中調用另一個建構函式,會產生一個臨時對象,並且立即釋放。 
string c=a;只調用了拷貝建構函式。而string c; c=a;分別調用了建構函式和賦值函數。

建構函式和解構函式的注意點:
1、建構函式和解構函式不能有傳回值
2、可以顯式調用建構函式和解構函式
3、拷貝(複製)建構函式不能用值傳遞
4、不要在建構函式和解構函式中拋出異常和調用有異常拋出的函數,可能會有記憶體泄露!
5、確定基類有虛解構函式

二、static、const、友元與虛函數

1.靜態成員使用static申明,在記憶體中永遠只有一份執行個體(靜態變數,類內聲明,類外定義)
2.是類的對象所共有的
3.靜態成員變數可以被成員函數訪問,但靜態成員函數只能訪問靜態成員變數
4.友元是為了一個普通函數直接存取一個類的保護甚至是私人成員的機制

虛函數:
在普通成員函數前面加 virtual 關鍵字
一個函數在基類申明一個virtual,那麼在所有的衍生類別都是是virtual的
一個函數在基類為普通函數,在衍生類別定義為virtual的函數稱為越位

抽象類別:
具有純虛函數的類就是抽象類別
抽象類別不能被執行個體化,所以抽象類別只能以指標方式被應用
抽象類別可以防止切片的發生
抽象類別不產生虛表。

const對象與成員:
1.const對象只能訪問const成員函數,而非const對象可以訪問任意的成員函數,包括const成員函數.
2.const對象的成員是不可修改的,然而const對象通過指標維護的對象卻是可以修改的.
3.const成員函數不可以修改對象的資料,不管對象是否具有const性質。
4.然而加上mutable修飾符的資料成員,對於任何情況下通過任何手段都可修改,此時的const成員函數是可以修改它的

三、設計與實現

C++物件導向編程中一條重要的規則是:公有繼承意味著 "是一個" 。一定要牢牢記住這條規則。

C++有兩種多態多態形式:
1、編譯時間刻多態,編譯時間刻多態依靠函數重載或者模板實現
2、運行時刻多態。運行時刻多態依靠需函數虛介面實現

引用的使用原則:
1.在可以用引用的情況下,不要用指標
2.引用可以作為“左值”
3.引用不允許為空白,當存在對象為空白時,必須使用指標。 引用指向一個空值,是非常有害的!
4.盡量用“傳引用”而不用“傳值”
5.必須返回一個對象時不要試圖返回一個引用
6.千萬不要返回局部對象的引用,也不要返回函數內部用new初始化的指標的引用

類中有const資料,必須要有建構函式對它初始化。
static const double a;       //靜態double常量聲明!
const double 類名::a=1.04;   //靜態初始化!

T& operator[](int index); //傳回數組的一個元素,可讀,可寫
const T& operator[](int index)const;  //傳回數組的一個元素,可讀,不可寫

重載函數,區分是不是重載函數的標準:
(1)只能靠函數的參數來區分重載函數(類型、個數、預設參數)
(2)不能靠函數的傳回值來區分重載函數

四、C++與C的一些區別

C中struct和C++中struct的區別:
C++的struct可以當作class來用,區別是,class中的成員預設是private,而struct的成員預設為public。 
C中的struct只能是一些變數的集合體,可以封裝資料卻不可以隱藏資料,而且成員不可以是函數。 
C中的Struct是使用者自訂資料類型(UDT),C++中的Struct是抽象資料類型(ADT),支援成員函數的定義。 

C++語言擔保,如果p等於NULL,則delete p不作任何事情。
delete p 是一個兩步的過程:調用解構函式,然後釋放記憶體。
delete p調用的是operator delete(void*),而delete[] p調用的是operator delete[](void*)。

static 關鍵字至少有下列作用:   
(1)函數體內static變數的作用範圍為該函數體,不同於auto變數,該變數的記憶體只被分配一次, 因此其值在下次調用時仍維持上次的值;   
(2)在模組內的static全域變數可以被模組內所用函數訪問,但不能被模組外其它函數訪問;   
(3)在模組內的static函數只可被這一模組內的其它函數調用,這個函數的使用範圍被限制在聲明它的模組內; 
(4)在類中的static成員變數屬於整個類所擁有,對類的所有對象只有一份拷貝;   
(5)在類中的static成員函數屬於整個類所擁有,這個函數不接收this指標,因而只能訪問類的static成員變數。 

const 關鍵字至少有下列作用:   
(1)欲阻止一個變數被改變,可以使用const關鍵字。在定義該const變數時,通常需要對它進行初始化,因為以後就沒有機會再去改變它了;
(2)對指標來說,可以指定指標本身為const,也可以指定指標所指的資料為 const,或二者同時指 定為const;
(3)在一個函式宣告中,const可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;
(4)對於類的成員函數,若指定其為const類型,則表明其是一個常函數,不能修改類的成員變數;
(5)對於類的成員函數,有時候必須指定其傳回值為const類型,以使得其傳回值不為“左值”。

一個基類及其繼承類的實現:

class Base{    public:    Base(const char *s=NULL);    Base(const Base& rth);    Base & operator=(const Base & oth);    virtual ~Base();    private:    char *m_data;};Base::Base(const char* s){    if(s==NULL)    {        m_data=new char[1];        m_data[0]='\0';    }    else    {        int length=strlen(s);        m_data=new char[length+1];        strcpy(m_data,s);    }}Base::Base(const Base & oth){    int len=strlen(oth.m_data);    m_data=new char[len+1];    strcpy(m_data,oth.m_data);}Base & Base::operator=(const Base & oth){    if(this==&oth) return *this;    delete []m_data;    int len=strlen(oth.m_data);    m_data=new char[len+1];    strcpy(m_data,oth.m_data);    return *this;}Base::~Base(){    delete[] m_data;}class Derived : public Base{    public:    Derived(const char* s=NULL,int a=0);    Derived(const Derived& oth);    Derived& operator=(const Derived& oth);    private:    int m;};Derived::Derived(const char* s,int a):Base(s),m(a){ }Derived::Derived(const Derived& oth):Base(oth),m(oth.m){ }Derived& Derived::operator=(const Derived& oth){    if(this==&oth) return *this;    Base::operator=(oth);    m=oth.m;    return *this;}

C++編譯器不支援模板標頭檔和實現代碼分離的編譯

在分離式編譯的環境下,編譯器編譯某一個.cpp檔案時並不知道另一個.cpp檔案的存在,也不會去尋找(當遇到未決符號時它會寄希望於連接器)。這種模式在沒有模板的情況下運行良好,但遇到模板時就不行,因為模板僅在需要的時候才會具現化出來,所以,當編譯器只看到模板的聲明時,它不能具現化該模板,只能建立一個具有外部串連的符號並期待連接器能夠將符號的地址決議出來。然而當實現該模板的.cpp檔案中沒有用到模板的具現體時,編譯器懶得去具現,所以,整個工程的.obj中就找不到一行模板具現體的二進位代碼,於是連接器也傻了!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.