C++多態的概念

   在人類最初的時候,你們都是用手吃飯的,可是隨着人類的漫長髮展,漸漸的開始出現等級制度,部落,再以後,就是國家。每一個國家的人吃飯的方式都不同,英國人用刀叉吃飯,中國人用筷子吃飯。因此,若是想用程序來表現就是,現有一個基類(父類),
ide

class Human {

public:
	void eating( void ) {

		cout << "use hand to eat" << endl;
	}
};

   接着,在父類的基礎上,誕生了派生類,英國人,中國人,
函數

class Englishman : public Human {

public:
	//覆寫
	void eating(void) {

		cout << "use knife to eat" << endl;
	}
};

class Chinese : public Human {

public:
	void eating(void) {

		cout << "use chopstick to eat" << endl;
	}
};

   子類繼承了父類的函數,並對其進行修改,固然只是修改函數的內容,並無修改函數的返回值類型,函數名,函數參數,這種叫作函數的「覆寫」。那麼,我如今在global space區域實現一個函數,
this

void test_eating(Human& h) {

	h.eating();
}

   接着,我在主函數中,建立三個對象,
spa

        Human h;
	Englishman e;
	Chinese c;

   而後,我去調用這個test_eating()函數,指針

        test_eating(h);
	test_eating(e);
	test_eating(c);

   那麼,輸出結果會是什麼呢?
對象

7e7449cf8ce4e06b4d7f12da90360f1d.png-wh_

   很明顯,這不是咱們想要的結果,咱們明明建立了Englishman對象,Chinese對象,調用test_eating()函數時,卻沒法輸出本身類內部的函數。爲了解決這一問題,咱們只要在父類中,對
blog

void eating( void )

這個函數,把它變爲虛函數就好了。只要在函數前加上virtual。實現方式以下:繼承

virtual void eating( void )

對於這種作同一件事,處理的方式卻不一樣,這種在C++中被稱做是「多態」。也就是說,採用相同的調用方法,對於不一樣的對象,會調用不一樣的類裏面的函數。get

   當咱們把eating函數變爲虛函數的時候,咱們的目的就達成了。
it

697abad91883f087542cd1fcaa671b0f.png-wh_

   那麼多態採用的是什麼樣的一種機制呢?對於通常的函數,也就是非虛函數,採用的是靜態聯編,也就是說,非虛函數,在編譯時就肯定好了要調用哪一個函數。而對於動態聯編,是在運行時才肯定調用的是哪個函數。那麼動態聯編是如何作到的呢?當一個類內有虛函數時,基於這個類所建立的對象內部都會有一個指針,這個指針指向了虛函數表,當咱們調用函數時,就會根據這個指針找到虛函數表,從而調用虛函數。

   那麼多態的使用有沒有什麼特色呢?1.若是調用函數時,傳的是值,那麼就沒有多態,只有傳的是指針或引用纔會有多態。傳值時只能是靜態聯編。2.只有類的成員函數才能聲明爲虛函數。3,靜態成員函數不能是虛函數。4.內聯函數不能是虛函數。5.構造函數不能是虛函數。6.析構函數通常都聲明爲虛函數。7.重載函數不可設置爲虛函數。

   有個很關鍵的一點就是,若是要把函數設置爲虛函數,那麼,就得保證函數名相同,函數參數列表相同,函數返回值也應該相同。代碼以下:

class Person {

public:
    virtual void test( void )
    {
        cout << "Human test() " << endl;
     }

}

class Englishman {

public:
    virtual void test( void ){
        
        cout << "Englishman test()" << endl;
    }

}

class Chinese {

public:
    virtual void test( void ){
    
        cout << "Chinese test()" << endl;
    }
}

   這個時候,設置爲虛函數徹底是能夠的。固然也有例外。就是,能夠函數返回值不一樣。函數的返回值類型跟它的類的類型徹底相同,是它的類的指針或引用。代碼以下:

class Person {

public:
    virtual Person* test( void )
    {
        cout << "Human test() " << endl;
        return this;
     }

}

class Englishman {

public:
    virtual English* test( void ){
        
        cout << "Englishman test()" << endl;
        return this;
    }

}

class Chinese {

public:
    virtual Chinese test( void ){
    
        cout << "Chinese test()" << endl;
        return this;
    }
}

   這樣作是徹底能夠的。

相關文章
相關標籤/搜索