一個類能夠派生自多個類,這意味着,它能夠從多個基類繼承數據和函數。定義一個派生類,咱們使用一個類派生列表來指定基類。類派生列表以一個或多個基類命名,形式以下:ios
// 派生類 class Rectangle: public Shape { public: int getArea() { return (width * height); } };
多繼承即一個子類能夠有多個父類,它繼承了多個父類的特性。程序員
C++ 類能夠從多個類繼承成員,語法以下:編程
class <派生類名>:<繼承方式1><基類名1>,<繼承方式2><基類名2>,… { <派生類類體> };
C++ 容許在同一做用域中的某個函數和運算符指定多個定義,分別稱爲函數重載和運算符重載。函數
重載聲明是指一個與以前已經在該做用域內聲明過的函數或方法具備相同名稱的聲明,可是它們的參數列表和定義(實現)不相同。this
當您調用一個重載函數或重載運算符時,編譯器經過把您所使用的參數類型與定義中的參數類型進行比較,決定選用最合適的定義。選擇最合適的重載函數或重載運算符的過程,稱爲重載決策。spa
在同一個做用域內,能夠聲明幾個功能相似的同名函數,可是這些同名函數的形式參數(指參數的個數、類型或者順序)必須不一樣。您不能僅經過返回類型的不一樣來重載函數。指針
#include <iostream> using namespace std; class printData { public: void print(int i) { cout << "Printing int: " << i << endl; } void print(double f) { cout << "Printing float: " << f << endl; } void print(char* c) { cout << "Printing character: " << c << endl; } }; int main(void) { printData pd; // Call print to print integer pd.print(5); // Call print to print float pd.print(500.263); // Call print to print character pd.print("Hello C++"); return 0; }
您能夠重定義或重載大部分 C++ 內置的運算符。這樣,您就能使用自定義類型的運算符。對象
重載的運算符是帶有特殊名稱的函數,函數名是由關鍵字 operator 和其後要重載的運算符符號構成的。與其餘函數同樣,重載運算符有一個返回類型和一個參數列表。繼承
Box operator+(const Box&);
// 重載 + 運算符,用於把兩個 Box 對象相加 Box operator+(const Box& b) { Box box; box.length = this->length + b.length; box.breadth = this->breadth + b.breadth; box.height = this->height + b.height; return box; }
多態按字面的意思就是多種形態。當類之間存在層次結構,而且類之間是經過繼承關聯時,就會用到多態。接口
C++ 多態意味着調用成員函數時,會根據調用函數的對象的類型來執行不一樣的函數。
虛函數 是在基類中使用關鍵字 virtual 聲明的函數。在派生類中從新定義基類中定義的虛函數時,會告訴編譯器不要靜態連接到該函數。
咱們想要的是在程序中任意點能夠根據所調用的對象類型來選擇調用的函數,這種操做被稱爲動態連接,或後期綁定。
您可能想要在基類中定義虛函數,以便在派生類中從新定義該函數更好地適用於對象,可是您在基類中又不能對虛函數給出有意義的實現,這個時候就會用到純虛函數。
class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } // pure virtual function virtual int area() = 0; };
= 0 告訴編譯器,函數沒有主體,上面的虛函數是純虛函數。
首先:強調一個概念
定義一個函數爲虛函數,不表明函數爲不被實現的函數。
定義他爲虛函數是爲了容許用基類的指針來調用子類的這個函數。
定義一個函數爲純虛函數,才表明函數沒有被實現。
定義純虛函數是爲了實現一個接口,起到一個規範的做用,規範繼承這個類的程序員必須實現這個函數。
一、簡介
假設咱們有下面的類層次:
#include <iostream> using namespace std; class A { public: virtual void foo() { cout<<"A::foo() is called"<<endl; } }; class B:public A { public: void foo() { cout<<"B::foo() is called"<<endl; } }; int main(void) { A *a = new B(); a->foo(); // 在這裏,a雖然是指向A的指針,可是被調用的函數(foo)倒是B的! return 0; }
運行結果:
B::foo() is called
這個例子是虛函數的一個典型應用,經過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並非在編譯時刻被肯定的,而是在運行時刻被肯定的。因爲編寫代碼的時候並不能肯定被調用的是基類的函數仍是哪一個派生類的函數,因此被成爲「虛」函數。
虛函數只能藉助於指針或者引用來達到多態的效果
一、純虛函數聲明以下: virtual void funtion1()=0; 純虛函數必定沒有定義,純虛函數用來規範派生類的行爲,即接口。包含純虛函數的類是抽象類,抽象類不能定義實例,但能夠聲明指向實現該抽象類的具體類的指針或引用。
二、虛函數聲明以下:virtual ReturnType FunctionName(Parameter) 虛函數必須實現,若是不實現,編譯器將報錯,錯誤提示爲:
error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"
三、對於虛函數來講,父類和子類都有各自的版本。由多態方式調用的時候動態綁定。
四、實現了純虛函數的子類,該純虛函數在子類中就編程了虛函數,子類的子類即孫子類能夠覆蓋該虛函數,由多態方式調用的時候動態綁定。
五、虛函數是C++中用於實現多態(polymorphism)的機制。核心理念就是經過基類訪問派生類定義的函數。
六、在有動態分配堆上內存的時候,析構函數必須是虛函數,但沒有必要是純虛的。
七、友元不是成員函數,只有成員函數才能夠是虛擬的,所以友元不能是虛擬函數。但能夠經過讓友元函數調用虛擬成員函數來解決友元的虛擬問題。
八、析構函數應當是虛函數,將調用相應對象類型的析構函數,所以,若是指針指向的是子類對象,將調用子類的析構函數,而後自動調用基類的析構函數。