1. 程式人生 > >孫鑫視訊---掌握C++

孫鑫視訊---掌握C++

C++經典語法與應用,類的編寫與應用,構造與解構函式,函式的過載,類的繼承,函式覆蓋,基類與派生類的建構函式、解構函式先後呼叫順序,如何在派生類建構函式中向基類的建構函式傳遞引數,this成員變數,型別轉換的內幕,虛擬函式與多型性,引用和指標的變數的區別與共同處。

VC工程的編譯原理與過程,將工程中不同的類拆分到不同的原檔案中,每一個類由一個.h和.cpp檔案共同完成,標頭檔案重複定義問題的解決,培養了學員良好的程式設計習慣,也為以後分析MFC Appwizard生成的工程奠定了良好基礎。

C++的標準輸入輸出流

C++中提供了一套輸入輸出流類的物件,它們是cin 、cout和cerr,對應c語言中的三個檔案指標stdin、stdout、stderr,分別指向終端輸入、終端輸出和標準出錯輸出(也從終端輸出)。

cin與>>一起完成輸入操作,cout、cerr與<<一起完成輸出與標準錯誤輸出。

利用cin和cout比C語言中的scanf和printf要方便得多,cin和cout可以自動判別輸入輸出資料型別而自動調整輸入輸出格式,不必像scanf和printf那樣一個個由使用者指定。使用cin,cout不僅方便,而且減少了出錯的可能性。

對於輸出來說,我們像以上方式呼叫就可以了,對於輸入來說,我們以如下方式呼叫即可:

int i; cin>>i;

注意箭頭的方向。在輸出中我們還使用endl(end of line),表示換行,注意最後一個是字元‘l’,而不是數字1,endl相當於C語言的'\n',表示輸出一個換行。

#include <iostream>
using namespace std;
//定義結構體
//struct Point
class Point
{
public://表示所有資料成員都可以在外部訪問
//private:私有,對外資料成員都不可訪問
//protected:子類和父類之間的訪問
    int x;
    int y;
    void output()
    {
        cout<<x<<endl<<y<<endl;
    }
};
void main()
{
    Point pt;
    pt.x
=5; pt.y=5; //cout<<pt.x<<endl<<pt.y<<endl; pt.output(); }

建構函式

1、建構函式最重要的作用是建立物件本身

2、C++規定,每個類必須有一個建構函式,沒有建構函式,就不能建立任何物件

3、C++又規定,如果一個類沒有提供任何的建構函式,則C++提供一個預設的建構函式(由C++編譯器提供),這個預設的建構函式是一個不帶引數的建構函式,它只負責建立物件,而不做任何的初始化工作

4、只要一個類定義了一個建構函式,不管這個建構函式是否是帶引數的建構函式,C++就不再提供預設的建構函式。也就是說,如果為一個類定義了一個帶引數的建構函式,還想要無引數的建構函式,則必須自己定義

#include <iostream>
using namespace std;
//定義結構體
//struct Point
class Point
{
public://表示所有資料成員都可以在外部訪問
    int x;
    int y;
/*    void init()
    {
        x=0;
        y=0;
    };*/
    Point()//建構函式,用於建立物件本身
    {
        x=0;
        y=0;
    }
    void output()
    {
        cout<<x<<endl<<y<<endl;
    }
};
void main()
{
    Point pt;//例項化一個物件
    //pt.init();
    //pt.x=5;
    //pt.y=5;
    //cout<<pt.x<<endl<<pt.y<<endl;
    pt.output();
}

 

解構函式

1、當一個物件生命週期結束時,其所佔有的記憶體空間就要被回收,這個工作就由解構函式來完成。

2、解構函式是“反向”的建構函式,解構函式不允許有返回值,更重要的是解構函式不允許帶引數,並且一個類中只能有一個解構函式。

3、解構函式的作用正好與建構函式相反,物件超出其作用範圍,對應的記憶體空間被系統收回或被程式用delete刪除時,解構函式被呼叫。

4、根據解構函式的這種特點,我們可以在建構函式中初始化物件的某些成員變數,給其分配記憶體空間(堆記憶體),在解構函式中釋放物件執行期間所申請的資源。

#include <iostream>
using namespace std;
class Point
{
public://表示所有資料成員都可以在外部訪問
    int x;
    int y;
/*    void init()
    {
        x=0;
        y=0;
    };*/
    Point()
    {
        x=0;
        y=0;
    }
    ~Point()//解構函式,生命週期結束的時候呼叫這個函式進行空間釋放,系統自動完成
    {
    }
    void output()
    {
        cout<<x<<endl<<y<<endl;
    }
};
void main()
{
    Point pt;//例項化一個物件
    pt.output();
}

 

函式的過載

過載構成的條件:函式的引數型別、引數個數不同,才能構成函式的過載。

分析以下兩種情況,是否構成函式的過載。

第一種情況:(1)void output();

                     (2)int output();

只有返回值不同的兩個函式不能構成函式的過載

 

第二種情況:(1)void output(int a,int b=5);

                     (2)void output(int a);

帶預設值也是不能構成函式過載

this指標

1、this指標是一個隱含的指標,它是指向物件本身,代表了物件的地址

2、一個類所有的物件呼叫的成員函式都是同一程式碼段。那麼成員函式又是怎麼識別屬於同一物件的資料成員呢?

     原來,在物件呼叫pt.output(10,10)時,成員函式除了接受2個實參外,還接受到了一個物件s的地址。這個地址被一個隱含的形參this指標所獲取,它等同於執行this=&pt

     所有對資料成員的訪問都隱含地被加上字首this->。例如:x=0; 等價於 this->x=0

在以後的MFC程式設計中,如果在成員函式中想呼叫同類中的某個成員,可以使用VC++提供的自動列出成員函式功能,使用this->,VC++將列出該類中的所有成員,我們可以從列表中選擇我們想呼叫的成員。

自動列出成員函式功能,可以提高編寫速度,減少拼寫錯誤。我們經常不能完全記住某個函式的完整拼寫,但卻能夠從列表中辨別出該函式,自動列出成員函式的功能在這時就顯得更加有用了。

事實上,在各種IDE程式設計環境中,我們通常都不可能記住也沒有必要記住所有的函式,只要將常用的函式記住,其他不常用的函式只要記住其大概的寫法和功能,在呼叫該函式時可以從自動列出成員函式中選取,這樣可以大大節省我們的學習時間。

我們不用花費大量的時間去死記硬背許多函式,利用自動列出成員函式功能和幫助系統,就能夠在程式設計時順利地使用這些函式,等用的次數多了,也就在不知不覺中完全掌握了這些函式。

#include <iostream>
using namespace std;
class Point
{
public://表示所有資料成員都可以在外部訪問
    int x;
    int y;
/*    void init()
    {
        x=0;
        y=0;
    };*/
    Point()
    {
        x=0;
        y=0;
    }
    Point(int a,int b)//函式的過載
    {
        x=a;
        y=b;
    }
    ~Point()//解構函式,生命週期結束的時候呼叫這個函式進行空間釋放,系統自動完成
    {
    }
    void output()
    {
        cout<<x<<endl<<y<<endl;
    }
    void output(int x,int y)
    {
        this->x=x;
        this->y=y;
    }
};
void main()
{
    Point pt(3,3);//例項化一個物件
    pt.output(5,5);
    pt.output();
}

 

類的繼承

在C++中,給我們提供了一種重要的機制,就是繼承。 理解繼承是理解面向物件程式設計的關鍵。

#include<iostream>
using namespace std;
class Animal
{
public:
    void eat()
    {
        cout<<"animal eat"<<endl;
    }
    void sleep()
    {
        cout<<"animal sleep"<<endl;
    }
    void breathe()
    {
        cout<<"animal breathe"<<endl;
    }
};
class Fish:public Animal//Animal是基類(父類),Fish是派生類(子類)
{

};
void main()
{
    Animal an;
    an.eat();
    Fish fh;
    fh.sleep();
}

訪問許可權

#include<iostream>
using namespace std;
class Animal
{
public:
    void eat()
    {
        cout<<"animal eat"<<endl;
    }
protected://保護,對於子類是可以訪問,在外部不可以被訪問
    void sleep()
    {
        cout<<"animal sleep"<<endl;
    }
private://私有方法,在子類中不可以訪問
    void breathe()
    {
        cout<<"animal breathe"<<endl;
    }
};
class Fish:public Animal//Animal是基類(父類),Fish是派生類(子類)
{
    void test()
    {
        sleep();
        //breathe();
    }

};
void main()
{
    Animal an;
    an.eat();
    Fish fh;
    //fh.sleep();//保護的方法不能在外部訪問
}

類的繼承訪問特性

#include<iostream>
using namespace std;
class Animal
{
public:
    Animal()
    {
        cout<<"animal construct"<<endl;
    }
    ~Animal()
    {
        cout<<"animal decconstruct"<<endl;
    }
    void eat()
    {
        cout<<"animal eat"<<endl;
    }
    void sleep()
    {
        cout<<"animal sleep"<<endl;
    }
    void breathe()
    {
        cout<<"animal breathe"<<endl;
    }
};
class Fish:public Animal
{
public:
    Fish()
    {
        cout<<"fish construct"<<endl;
    }
    ~Fish()
    {
        cout<<"fish decconstruct"<<endl;
    }
};
void main()
{
    Fish fh;
    
}

輸出結果:

 

函式的覆蓋

函式的覆蓋是發生在父類與子類之間

#include<iostream>
using namespace std;

class Animal
{
public:
    Animal(int height,int weight)
    {
        cout<<"animal construct"<<endl;
    }
    ~Animal()
    {
        cout<<"animal decconstruct"<<endl;
    }
    void eat()
    {
        cout<<"animal eat"<<endl;
    }
    void sleep()
    {
        cout<<"animal sleep"<<endl;
    }
    void breathe()
    {
        cout<<"animal breathe"<<endl;
    }
};



class Fish:public Animal
{
public:
    Fish():Animal(400,300),a(1)
    {
        //cout<<"fish construct"<<endl;
    }
    ~Fish()
    {
        //cout<<"fish decconstruct"<<endl;
    }
    void breathe()
    {
        Animal::breathe();//::表示作用域識別符號,表示這個函式是屬於哪個類的
        cout<<"fish bubble"<<endl;
    }
private:
    const int a;
};


void main()
{
    Fish fh;
    fh.breathe();
    
}

輸出結果:

animal construct
animal breathe
fish bubble
animal decconstruct

函式的多型

多型性 當C++編譯器在編譯的時候,發現Animal類的breathe()函式是虛擬函式,這個時候C++就會採用遲繫結(late binding)的技術,在執行時,依據物件的型別(在程式中,我們傳遞的Fish類物件的地址)來確認呼叫的哪一個函式,這種能力就做C++的多型性。

#include<iostream>
using namespace std;

class Animal
{
public:
    Animal(int height,int weight)
    {
        //cout<<"animal construct"<<endl;
    }
    void eat()
    {
        cout<<"animal eat"<<endl;
    }
    void sleep()
    {
        cout<<"animal sleep"<<endl;
    }
    virtual void breathe() //多型性:virtual 定義虛擬函式 會採用遲繫結,子類如果有就呼叫子類的,子類如果沒有就呼叫父類的
    {
        cout<<"animal breathe"<<endl;
    }
};



class Fish:public Animal
{
public:
    Fish():Animal(400,300),a(1)
    {
        //cout<<"fish construct"<<endl;
    }
    ~Fish()
    {
        //cout<<"fish decconstruct"<<endl;
    }
    void breathe()
    {
        //Animal::breathe();//::表示作用域識別符號,表示這個函式是屬於哪個類的
        cout<<"fish bubble"<<endl;
    }
private:
    const int a;
};

void fn(Animal *pAn)
{
    pAn->breathe();
}



void main()
{
    Fish fh;
    Animal *pAn;
    pAn=&fh;
    fn(pAn);
}

純虛擬函式  virtual void breathe()=0;

指被表明為不具體實現的虛成員函式

純虛擬函式讓類先具有操作的名稱而沒有具體的內容,讓派生類在繼承的時候,再具體給出定義