一般來說,假如用類A來聲明一個指針,之後不管它是指向類A的對象還是類B的對象,p都是調用類A的方法。
例如:B類繼承A類,並且重新定義了函數print()。
<pre name="code" class="html"><span style="font-size:18px;">class A {
void print() {
print("A");
}
}
class B : public class A {
void print() {
<span style="white-space:pre"> </span>print("B");
}
}
A *p;
A a;
B b;
p = &a;
p.print(); //調用類A的print()方法
p = &b;
p.print(); //還是調用類A的print()方法</span>
這就是c++中的靜態聯編,在編譯時靜態地通過左值的類型來判定所調用的方法。
爲了能夠在運行時動態的根據實例的不同來調用具體的方法,我們可以使用虛函數;
在基類函數前面加上 關鍵字virtual,派生類中函數前面可以加上virtual,也可以不用加
<span style="font-size:18px;">class A {
virtual void print() {
}
}
class B {</span><pre name="code" class="cpp"><span style="font-size:18px;">class people {
public: virtual void print() = 0;
}
class man: public people {
public: virtual void print() {
print("man");
}
}
class woman: public people {
public: virtual void print() {
print("woman");
}
}</span>
virtual void print() { }} 這樣,在類中的函數方法的類型前面加上關鍵字 virtual,
就可以在運行時就會具體根據p的實例是哪一個來調用相關的方法了。
其實虛函數就是指在編譯的時候不能確定要調用哪個實例的函數,而是要在運行時動態的決定將要調用哪個函數。
其中要求基類中與派生類中的函數名,參數名,參數類型都要相同。
並且其中p只能由基類A聲明,即不能用派生類聲明的指針指向基類的實例,即使是虛函數也不行。
純虛函數:就只是在基類中聲明這個函數,但是不實現它,由派生類自己實現函數。
<span style="font-size:18px;">class people {
public: virtual void print() = 0;
}
class man: public people {
public: virtual void print() {
print("man");
}
}
class woman:public people {
public:virtual void print() {
print("woman");
}
}</span>
所以在下面調用時就直接根據對象的實例來調用相應的方法
<span style="font-size:18px;">man m;
woman w;
m.print(); // 打印 man
w.print(); // 打印woman</span>