寒假MOOC學習計划


寒假MOOC學習計划

課程網址: https://www.icourse163.org/course/0809CAU007-432001


選課理由

該課程為C++國家精品課程,好評如潮。


學習計划

每天學習一小節,兩到三天完成一個章節。


學習筆記 02.06

面向對象程序設計方法(1):

  • 面向對象(object-oriented)

  • 數據分散管理策略數據集中管理策略

    分別對應局部變量和全局變量的使用。

  • 類的封裝

    通過設定訪問權限封裝類成員,將需要訪問的成員開放,不需訪問的成員隱藏,避免誤訪問。

    – 公有權限(public
    – 私有權限(private
    – 保護權限(protected

  • 類的接口

    – 公有成員是封裝后類對外的接口
    – 一個類必須有公有成員,否則這個類無法使用
    – 開放用戶正常使用所必須的成員,隱藏不需被直接訪問的成員

  • 類的定義

    – 聲明數據成員的語法形式類似於定義變量,所不同的是聲明數據成員不能初始化
    – 編譯器默認將直接定義在類聲明部分大括號里的函數成員當做內聯函數
    – 類的默認訪問權限為private,每個類成員都有且只有一種訪問權限

  • 對象的定義訪問

    類相當於是程序員自己定義的一種新的數據類型,可稱為類類型。

    定義對象和定義變量的語法形式基本相同。

    –訪問對象就是通過公有成員接口操作內存中的對象,實現特定的程序功能
    –訪問對象中的公有成員需使用.運算符
    –用對象指針訪問則需要使用->運算符


學習筆記 02.07

面向對象程序設計方法(2):

  • 類與對象的編譯原理

    – 每個對象所占用的內存空間都等於類中全部數據成員所需內存空間的總和
    – 多個同類對象共用同一個函數,內存中只需要保存一份函數代碼
    – 編譯器會自動進行調整↓

  • 構造函數

    – 構造函數由計算機自動調用,程序員不能直接調用
    – 構造函數沒有返回值,定義時不能寫函數類型,寫void也不行
    – 構造函數通常是類外調用,其訪問權限不能設為private
    – 類如果未定義構造函數,編譯器將添加默認構造函數,形式為 類名(){}
    – 類如果未定義拷貝構造函數,編譯器將添加默認拷貝構造函數(數據成員一一對應拷貝)

  • 析構函數

    – 析構函數由計算機自動調用,程序員不能直接調用
    – 析構函數沒有形參
    – 析構函數沒有返回值,定義時不能寫函數類型,寫void也不行
    一個類只能有一個析構函數
    – 析構函數通常是類外調用,其訪問權限不能設為private
    – 類如果未定義析構函數,編譯器將自動添加默認析構函數,形式為 ~類名(){}

  • 拷貝構造函數中的深拷貝淺拷貝

    默認拷貝構造函數執行淺拷貝。
    對於動態分配的數據成員,淺拷貝只拷貝指針,並沒有再分配內存,而深拷貝則需要程序員編寫拷貝構造函數再分配新的內存空間。

  • 類與對象編程的主要內容

    – 定義類。程序員在定義一個類的時候要考慮到5大要素,即數據成員、函數成員、各成員的訪問權限、構造函數和析構函數
    – 定義對象。將類當作一種自定義數據類型來定義變量,所定義的變量就稱為對象
    – 訪問對象。訪問對象就是通過接口(即公有成員)操作內存中的對象,實現特定的程序功能


學習筆記 02.08

面向對象程序設計方法(3):

  • 對象數組

    有多少個數組元素,就會調用多少次構造函數和析構函數。

  • 對象作為函數的形參

    – 值傳遞與常對象
    – 引用傳遞與常引用
    – 指針傳遞與指向常對象的指針

  • 常數據成員

    – 在類定義中聲明常數據成員需使用關鍵字const進行限定,聲明時不能初始化
    – 為構造函數添加初始化列表對常數據成員進行初始化的唯一途徑
    – 定義對象時必須初始化常數據成員

  • 常函數成員

    – 聲明、定義常函數成員需在函數頭后面加關鍵字const進行限定
    – 常函數成員只能讀類中的數據成員,不能賦值修改
    – 常函數成員只能調用其它常函數成員
    – 通過常對象只能調用其常函數成員
    – 除形參個數、類型之外,還可以用關鍵字const區分類中的重載函數

  • 靜態數據成員

    – 在類定義中聲明靜態數據成員需使用關鍵字static進行限定,聲明時不能初始化
    – 必須在類聲明的大括號對靜態成員進行定義及初始化,定義時不能再加關鍵字static
    – 在類外其它函數中訪問靜態數據成員需以類名::靜態數據成員名的形式訪問,或通過任何一個該類對象以對象名.靜態數據成員名的形式訪問
    – 類外訪問受權限約束,只能訪問公有的靜態數據成員
    – 靜態數據成員是靜態分配的,程序加載后立即分配內存,直到程序執行結束退出時才被釋放
    – 私有靜態數據成員具有類作用域,公有靜態數據成員具有文件作用域

  • 靜態函數成員

    – 聲明時使用關鍵字static進行限定,定義時不能再使用關鍵字static
    靜態函數成員只能訪問類中的靜態成員
    – 在類外調用靜態函數成員需以類名::靜態函數成員名()的形式調用,或通過任何一個該類對象以對象名.靜態函數成員名()的形式調用
    – 類外調用受權限約束,只能調用公有的靜態函數成員
    靜態函數成員不能再聲明為常函數
    靜態函數成員不推薦聲明為內聯函數,因為編譯器在編譯時會調整內聯函數,此時所訪問的靜態數據成員可能還未初始化,因此其數據是不可靠的,此時訪問會導致程序的運行結果出錯

  • 友元函數友元類

    – 在類聲明部分使用friend關鍵字聲明友元函數原型或友元類
    – 聲明語句可以放在大括號內的任意位置,該位置的訪問權限無影響
    – 友元函數是類外的其它函數,不是類的成員
    – 友元函數可以在其函數體內訪問該類對象的所有成員,不受權限約束
    – 友元類的所有成員函數都是該類的友元函數
    – 友元關系是單向的
    – 友元關系不能傳遞


學習筆記 02.09

面向對象程序設計方法(4):

  • 代碼重用

    結構化程序設計重用的是算法代碼。
    而面向對象程序設計,既重用算法代碼,也重用數據代碼。

  • 類的組合聚合

    – 數據成員中包含對象成員的類稱為組合類
    – 數據成員中包含對象指針的類稱為聚合類,聚合類是一種特殊形式的組合類
    – 聚合類的對象成員是獨立創建的,聚合類對象只包含指向對象成員的指針
    – 聚合類對象可以共用對象成員
    – 訪問組合類對象中對象成員的下級成員,受多級訪問權限控制
    – 組合類對象構造時,先調用對象成員構造函數,再執行組合類構造函數的函數體
    – 組合類對象析構時,先執行組合類析構函數的函數體,再調用對象成員析構函數
    – 多個對象成員之間由聲明順序決定(先聲明,先構造,后析構

  • 類的繼承派生

    – 派生類將繼承基類中除構造函數、析構函數之外的所有數據成員和函數成員
    – 繼承后,派生類會對其基類成員按照繼承方式進行再次封裝
    public公有繼承):
    派生類對其基類成員不做封裝,它們在派生類中的訪問權限與基類中相同
    private私有繼承):
    派生類對其基類成員做全封裝,它們在派生類中的訪問權限都被改為private
    protected保護繼承):
    派生類對其基類成員做半封裝,基類中的public成員被繼承到派生類后,其訪問權限被改成protected
    基類的private會被繼承,但不能被派生類直接調用,要使用基類接口訪問

    基類 繼承類型 子類
    public public public
    protected protected
    private 不能直接訪問
    public protected protected
    protected protected
    private 不能直接訪問
    public private private
    protected private
    private 不能直接訪問
  • 同名覆蓋

    派生類中定義與基類成員重名的新增成員,新增成員將覆蓋基類成員。
    同名覆蓋后,被覆蓋的基類成員仍然存在,只是被隱藏了。可以訪問被覆蓋的基類成員,其訪問形式是基類名 :: 基類成員名

  • 組合派生類的構造與析構

    – 派生類對象先調用基類構造函數,再執行派生類構造函數的函數體
    初始化基類成員和新增對象成員需通過初始化列表
    – 組合派生類的構造函數依次初始化基類成員->新增對象成員->新增非對象成員
    – 析構順序與構造順序相反
    – 多個基類之間由聲明順序決定(先聲明,先構造,后析構


學習筆記 02.10

面向對象程序設計方法(5):

  • 運算符重載

    – 運算符函數可定義為類的函數成員或類外的友元函數
    – 若運算符+被重載為類的函數成員,則調用形式為c1.+(c2),其中,c1是對象名,.是成員運算符,+是函數成員名,c2是實參
    – 若運算符+被重載為類的友元函數,則調用形式為+(c1, c2),其中,+是友元函數名,c1c2是實參
    – 五個不能重載的運算符是:
    條件運算符?:sizeof運算符,成員運算符.,指針運算符*,作用域運算符::
    – 重載后,運算符的優先級和結合性不會改變
    – 重載后,運算符的操作數個數不能改變
    – 類如果未重載=運算符,編譯器將添加默認重載(數據成員一一對應拷貝,淺拷貝)

    – 具體用法:


  • Liskov替換准則

    – 為了讓基類對象及其派生類對象之間可以重用代碼,C++語言制定了如下的類型兼容語法規則:
    • 派生類的對象可以賦值給基類對象
    • 派生類的對象可以初始化基類引用
    • 派生類對象的地址可以賦值給基類的對象指針

    – 應用類型兼容語法規則有1個前提條件和1個使用限制:
    • 前提條件:派生類必須公有繼承基類。
    • 使用限制:通過基類對象、引用或對象指針訪問派生類對象,只能訪問其基類成員

  • 虛函數

    – 只能在類聲明部分聲明虛函數,在類實現部分定義函數成員時不能使用virtual關鍵字
    – 基類中聲明的虛函數成員被繼承到派生類后,自動成為派生類的虛函數成員
    – 派生類可以重寫基類虛函數成員,如果重寫后的函數原型與基類虛函數成員完全一致,則該函數自動成為派生類的虛函數成員,無論聲明時加不加virtual關鍵字
    靜態函數、構造函數不能是虛函數
    析構函數可以是虛函數

    – 演示:

  • 多態性的實現

    – 定義基類時將需要自動調用派生類新增的同名函數成員定義成虛函數
    – 定義派生類時公有繼承基類,並重寫那些從基類繼承來的虛函數成員
    – 編寫類族共用的程序代碼時,定義基類引用基類對象指針來訪問該類族的對象

  • 純虛函數抽象類

    – 類定義中“只聲明,未定義”的函數成員被稱為純虛函數
    – 含有純虛函數成員的類就是抽象類
    – 抽象類不能實例化,但可以定義抽象類的引用、對象指針,所定義的引用、對象指針可以引用或指向其派生類的實例化對象

    – 抽象類可以作為基類定義派生類
    • 純虛函數成員只聲明了函數原型,沒有定義函數體代碼。因此派生類繼承純虛函數成員時,只是繼承其函數原型,即函數接口。派生類需要為純虛函數成員編寫函數體代碼,稱為實現純虛函數成員
    • 派生類如果實現了所有的純虛函數成員,那么它就變成了一個普通的類,可以實例化

    – 抽象類可以用來統一類族接口重用代碼

  • 多繼承

    派生類可以從多個基類繼承,這就是多繼承。多繼承派生類存在比較復雜的成員重名問題,其具體表現形式有3種:

    新增成員與基類成員重名
    • 如果通過派生類的對象名、引用或對象指針訪問派生類對象,則訪問到的是新增成員,此時新增成員覆蓋同名的基類成員(同名覆蓋
    • 如果通過基類的對象名、引用或對象指針訪問派生類對象,則訪問到的是基類成員,此時派生類對象被當作基類對象使用(Liskov替換准則
    • 如果基類定義虛函數成員,派生類公有繼承基類並重寫虛函數,那么通過基類的引用或對象指針訪問派生類對象所訪問到的將是新增的虛函數成員。這就是調用對象中虛函數成員時所呈現出的多態性(對象多態性

    多個基類之間的成員重名
    如果多個基類之間有重名的成員,同時繼承這些基類會造成派生類中基類成員之間的重名。訪問重名的基類成員,需在成員名前加基類名::

    同一基類被重復繼承
    多級派生時,從同一基類派生出多個派生類,這多個派生類再被多繼承到同一個下級派生類時,該下級派生類將包含多份基類成員的拷貝,也就是同一基類被重復繼承。此時,應當在派生類繼承基類時,將基類聲明為虛基類:class A1 : virtual public A


學習筆記 02.11

流類庫與文件讀寫:

  • C++語言的輸入與輸出

    – 提供輸入數據的數據源稱作輸入數據流
    – 輸出數據時的目的地稱作輸出數據流
    – 輸入數據流和輸出數據流統稱為輸入/輸出流

  • 輸入/輸出流中的數據緩沖區

  • 流類庫

    ios為基類的類族
    – 通用輸入/輸出流類:提供通用的輸入/輸出(簡稱標准I/O)功能
    – 文件輸入/輸出流類:提供文件輸入/輸出(簡稱文件I/O)功能
    – 字符串輸入/輸出流類:提供字符串輸入/輸出(簡稱字符串I/O)功能

  • 標准I/O
    #include<iostream>

    • 通用輸入流類istream及其對象cin
    – 使用提取運算符>>
    – 使用函數成員width設置下一輸入項的最大字符個數(含字符串結束符)
    – 使用函數成員get每次從流緩沖區中讀出1個字符

    • 通用輸出流類ostream及其對象cout
    – 使用插入運算符<<
    – 使用函數成員put每次輸出1個字符到流緩沖區中
    – 格式標記(Flag)是基類ios中定義的一組枚舉常量,用於表示不同的輸出格式。設置輸出格式,某些格式需使用函數成員flags,而另外一些格式需通過專門的函數成員,示例代碼:
    cout.flags(ios::hex); // 使用函數flags設置格式:以十六進制輸出整數

    – 格式操縱符(Manipulator)是流類庫中定義的一組函數,這些函數被分散定義在不同的頭文件中,示例代碼:

    // 頭文件:<iomanip>
    inline long setiosflags(long _l); // 設置某個格式標記,例如:setiosflags(ios::hex)
    inline long resetiosflags(long _l); // 將某個格式標記恢復到其默認值
    inline int setw(int _w); // 設置輸出位數,不足部分補空格。僅對下一個輸出項有效
    inline int setfill(int _m); // 設置填充字符。輸出位數不足部分補填充字符
    inline int setprecision(int _p); // 設置浮點數的輸出精度(即小數位數)
    cout << hex << setw(5) << 20; // 顯示結果:凵凵凵14,其中“凵”表示空格

    • 設定輸出位數及填充字符
    – 插入運算符 + 格式標記:cout.fill(‘#’); cout.width(6);
    – 插入運算符 + 格式操縱符:cout << setfill(‘#’) << setw(8);

    • 設定對齊方式
    – 插入運算符 + 格式標記:cout.flags(ios:: left);
    – 插入運算符 + 格式操縱符:cout << setiosflags(ios::left);

    • 設定浮點數的輸出格式
    – 插入運算符 + 格式標記:

    cout.flags(ios::fixed); // 定點表示法
    cout.precision(2); // 保留2位小數
    cout.flags(ios::scientific); //科學表示法

    – 插入運算符 + 格式操縱符:

    cout << setiosflags(ios::fixed); // 定點表示法
    cout << setprecision(2); // 保留2位小數
    cout << resetiosflags(ios::fixed); //取消定點格式
    cout << setiosflags(ios::scientific); //科學表示法
  • 文件I/O
    #include<fstream>

    fstream(const char *, int = ios::in); // 有參構造函數
    void open(const char *, int =ios::in); // 打開文件
    bool is_open() const; // 檢查文件是否正確打開
    void close(); // 關閉文件

    • 文件輸出流類ofstream及文件輸出
    – 【輸出文本文件

    – 【輸出二進制文件

    • 文件輸入流類ifstream及文件輸入
    – 【輸入文本文件

    – 【輸入二進制文件

    • 檢查輸入文件狀態
    eof()檢查文件是否已結束
    good()檢查文件是否已損壞

    • 文件打開模式

    • 文件的隨機讀寫
    – 文件輸入流對象包含一個讀文件指針
    – 文件輸出流對象包含一個寫文件指針

    istream& seekg(long bytes, ios::seek_dir origin); // 移動讀文件指針
    long tellg(); // 返回當前讀文件指針的位置
    ostream& seekp(long bytes, ios::seek_dir origin); // 移動寫文件指針
    long tellp(); // 返回當前寫文件指針的位置
  • string

    • 字符串類string
    – string類的函數成員

    str.length(); // 函數length返回字符串長度
    str.find("cd"); // 函數find查找子串"cd"的位置
    str.substr(2, 4); // 函數substr取出1個子串,從下標為2的元素開始取4個字符
    str.append("123"); // 函數append在串尾追加1個字符串

    – string類重載的運算符

    字符串比較:若果字符相等,則比較下一個字符,如果全部相等,那個字符較長那個大)

  • 字符串I/O
    #include <sstream>

    – 字符串I/O就是指在字符串對象和其它變量之間進行數據的輸入/輸出
    – 字符串輸入流類istringstream
    – 字符串輸出流類ostringstream
    – 字符串輸入/輸出流類stringstream

  • 基於Unicode編碼的流類庫

    基於Unicode編碼的流類庫以wios為基類,所有名稱前加w
    如預定義的寬字符流對象

    wistream wcin; // 寬字符的鍵盤對象wcin
    wostream wcout; // 寬字符的顯示器對象wcout

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: