GeekBand C++面向對象高級編程(上) First Week

C++的歷史與演化

C++起先是在C語言上面的一種拓展,后來演化到現在,已經是一門獨立且備受矚目的語言了。
語言關系圖: B -> C -> C++(new C -> C with class -> C++
演化路線圖: C++98 -> C++03 -> C++11 -> C++14

C++的幾種模式

C++本身被視作一個語言的聯邦,本身是一種多范型的語言。學好C++,需要了解一下的幾種C++的常用范型。

  • Clean C
  • Object-Oriented C++
  • Template C++
  • STL

C++原本的翻譯作為C plus plus, 第一版語言本身可以被稱作為C with Class。 對于Class這個名詞而言,C++有可以區分為OBP && OOP。
OBP本身是利用了C++對Data Resource的一種封裝,這里一般就是單個Class而已,很少與其他Class發生較多的交互。而OOP本身更多的使用了繼承與多態,而且OOP更加注重于Class與Class之間的關系。Class與Class之間的關系有繼承(inheritance),復合(composition)和委托(delegation)。

C++代碼的基本結構

C++的代碼一般分為聲明部分 && 實現部分。
聲明部分一般存放在.h .hpp結尾的文件中。 實現部分一般存放在.cc .cpp .C結尾的文件中。
為什么這里要區分聲明 && 實現呢。因為一個項目不可能只有一個文件,一般一個工程是多人協作式的。首先單個文件無法多人進行編輯。第二,如果每個人負責項目的一個模塊,一個只要關心自己的部分和他人與自己相關的部分了。如果實現與聲明相分離,相關的人員只需要在開發的時候約定聲明的部分,可以在開發過程中不關心實現,到最后進行代碼的集成測試就可以了。
C++的聲明文件為了防止多次包含有兩種技巧。一種是防御式聲明(ifndef), 一種使用#pragma once

  • 防御式聲明
// hello.h
#ifndef HELLO_H_
#define HELLO_H_
#endif // HELLO_H_
  • pragma
// hello.h
#pragma once

C++ Class

一般認為C++本身包括了C語言部分即Clean C。C語言的聲明 && 控制,C++基本與其類似。
C++的Class一般包含了構造與析構部分。構造是用來初始化一個對象,析構是對象生命周期結束后告訴編譯器如何刪除一個對象。構造函數和析構函數屬于特殊的函數。這兩種函數都是沒有返回值的。
C++的對象如果名稱叫做complex,那么構造函數就是complex(...), ...表示參數列表, 這里可以看出complex是可以有多個的,本身可以被重載。 析構函數就是~complex,析構函數是沒有參數列表的。C++如果不聲明構造函數或者析構函數的話。編譯器本身會給合成一個構造或者析構函數。合成的構造函數是沒有參數列表的。如果一個類中含有指針,最好自定義析構函數,否則合成的析構函數不會delete指針所對應的對象。

class complex {
public:
    complex(int re, int im); // 構造函數
    ~complex(); // 析構函數
private:
    int re_, im_;      
};

C++本身也有權限控制比如public, private, protected。
public表示在類以外也能被訪問,而private表示只能在類中被訪問。protected表示在被繼承的類中能夠被直接訪問。class默認是private類型的,struct 默認是public類型的。這個是class/struct聲明的兩者的根本區別。
這里有一個特點如果構造函數在private區域可以被用來實現單例模式。

// singleton
#include <iostream>
using namespace std;

class Singleton {
    Singleton() {}


    static Singleton *instance;

public:
    ~Singleton() { cout << "Singleton dtor" << endl; }

    struct GC {
            ~GC() { if(instance) { cout << "Delete Singleton" << endl; delete instance; } }
    };

private:
    static GC gc;

public:
    static Singleton *Instance() {
        if (!instance) {
            instance = new Singleton;
        }

        return instance;
    }

};

Singleton *Singleton::instance = NULL;
Singleton::GC gc;

int main()
{
    Singleton *s = Singleton::Instance();

    // delete t;

    return 0;
}

在C++中一個member function也可以是const的,這里表示this指針是const,所以不能修改類實例的成員變量的值。const的類實例變量只能調用const 方法

class complex {
public:
    complex(double r = 0, double i = 0) : re(r), im(i) {}
    complex &operator+=(const complex &);
    complex &operator-=(const complex &);
    complex &operator*=(const complex &);
    complex &operator/=(const complex &);
    double real() const { return re; }
    double imag() const { return im; }
private:
    double re, im;

    friend complex &__doapl(complex *, const complex &);
    friend complex &__doami(complex *, const complex &);
    friend complex &__doaml(complex *, const complex &);
};

{
       const complex c(1, 2);
       cout << c.real() << endl;
}

C++的函數傳值

  • pass by value
    通過值來傳遞給調用的函數,此時在調用的函數修改了值,原先的變量的值還是不會改變
void fun(int a)
{
    a += 1;
}

{
    int a = 10;
    fun(a);
    cout << a << endl; // 10 not 11
}
  • pass by reference/pointer
    通過引用來傳值,這里如果在調用的函數中修改了值,原先的值也會被修改。reference 編譯器的實現實際上是一個const pointer。
void fun(int a)
{
    a += 1;
}

{
    int a = 10;
    fun(a);
    cout << a << endl; // 11 not 10
}

Operator Overloading

C++自定義類型的一些operator是可以被重載的,比如+,+=,++,但是基本類型的是不可以的,這個會引起底層的混亂。

op  any of the following 38 operators:+ - * / % ? & | ~ ! = < > += -= *= /= %= ?= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> ( ) [ ]

1) overloaded operator;
2) [user-defined conversion function](http://en.cppreference.com/w/cpp/language/cast_operator);
3) [allocation function](http://en.cppreference.com/w/cpp/memory/new/operator_new);
4) [deallocation function](http://en.cppreference.com/w/cpp/memory/new/operator_delete);
5) [user-defined literal](http://en.cppreference.com/w/cpp/language/user_literal).

Synatax

operator op     (1)     
operator type   (2)     
operator new
operator new []     (3)     
operator delete
operator delete []  (4)     
operator "" suffix-identifier   (5)     (since C++11)
Expression As member function As non-member function Example
@a (a).operator@ ( ) operator@ (a) !std::cin calls std::cin.operator!()
a@b (a).operator@ (b) operator@ (a, b) std::cout << 42 calls std::cout.operator<<(42)
a=b (a).operator= (b) cannot be non-member std::string s; s = "abc"; calls s.operator=("abc")
a(b...) (a).operator()(b...) cannot be non-member std::random_device r; auto n = r(); calls r.operator()()
a[b] (a).operator cannot be non-member std::map<int, int> m; m[1] = 2; calls m.operator
a-> (a).operator-> ( ) cannot be non-member auto p = std::make_unique<S>(); p->bar() calls p.operator->()
a@ (a).operator@ (0) operator@ (a, 0) std::vector<int>::iterator i = v.begin(); i++ calls i.operator++(0)

in this table, @ is a placeholder representing all matching operators: all prefix operators in @a, all postfix operators other than -> in a@, all infix operators other than = in a@b

C++臨時變量

C++的臨時變量的產生一般和函數調用相關,一個調用如果沒有被一個左值接受,那么就可產生一個臨時變量,這個變量的生命周期是這條語句。這種變量在functor , 鏈式調用 和 一些使用到RAII的手法中經常會被使用到(比如Logger class)。臨時變量實際上和左值,右值有著密切的關系,以后有機會再詳細說明。

#include <iostream>
using namespace std;

class Temp {
public:
    Temp(int t) : t_(t) {}
    ~Temp() { cout << t_ << endl; }
private:
    int t_;
};

int main()
{
    cout << "---------- Begin ----------" << endl;

    Temp(1);  // 1
    Temp(2);  // 2

    cout << "---------- End ----------" << endl;

    return 0;
}

/*
output:
---------- Begin ----------
1
2
---------- End ---------- 
*/
// 這里1,2在End之前被打印出來,可以看出臨時變量的聲明周期就只有單條語句

總結

在這次課程中,我對對過去的知識做了一個完整的梳理與總結。感覺還是很不錯的。以后還需要認真學習。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容