虛函數就是實現函數的覆寫,
它們以下特點:
(1)不同的範圍(分別位於派生類與基類);
(2)函數名字相同;
(3)參數相同;
(4)基類函數必須有virtual關鍵字
還有,要注意一點,函數的返回值是影響不了覆寫和重載函數的.
我的以下程序,思路 不對的地方就是沒能完全理解多態的應用,
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A
{
};
class BA: public A
{
public:
int m_i;
int getValue()
{
return m_i;
}
};
class CA: public A
{
public:
string m_str;
string getValue()
{
return m_str;
}
};
class DA : public A
{
public:
vector <A *> m_vec;
};
int main()
{
BA *pBa = new BA;
pBa->m_i = 100;
CA *pCa = new CA;
pCa->m_str = "myprogram";
DA da;
da.m_vec.push_back(pBa);
da.m_vec.push_back(pCa);
//請問一下,我要在這裏輸出da.m_vec的所有內容,應該如何實現呢?
vector<A *> :: iterator it;
for (it = da.m_vec.begin(); it != da.m_vec.end(); it++)
{
(*it)->getValue(); // error,其類A沒有該虛函數實現.
}
return 0;
}
在以上程序中, CA的string getValue()函數和BA的int getValue()函數即使加了virtual ,也不能成爲多態,一是基類A沒有相應的虛函數,二是int 和string的返回類型不一致.因此,在實現輸出的話,需要在A類中寫一個純虛函數,然後在各自的子類上覆寫該虛函數,寫上分別的實現即可.
因此,可以寫成下面的樣子:
#include <iostream> #include <vector>
#include <string>
using namespace std;
class A
{
public:
void pout() { doout(); }
virtual void doout()=0;
};
class BA: public A
{
public:
void doout() { cout<<m_i<<" ";
}
int m_i;
};
class CA: public A
{
public:
void doout() { cout<<m_str<<" ";
}
string m_str;
};
class DA : public A
{
public:
void doout() {
for (vector<A *>::iterator
it=m_vec.begin();it!=m_vec.end();++it)
(*it)->doout();
}
vector <A *> m_vec;
};
int main()
{
BA *pBa = new BA;
pBa->m_i = 100;
CA *pCa = new CA;
pCa->m_str = "myprogram";
DA da;
da.m_vec.push_back(pBa);
da.m_vec.push_back(pCa);
da.doout();
return 0;
}
下面的網友邦的建議:
不要用這樣的語句
cout < < ((A *)(it))->getValue() < < endl;
由於返回類型不一致,很難在基類裏聲明。把輸出功能,放到派生類裏去,用一個基類虛函數調用。這樣就可以*it.foo()來實現輸出了。
是把輸出放到派生類的虛函數定義中,在基類用一個非虛函數調用虛函數來實現輸出。
=============================================================================================================
以下是重載和覆寫的區別?(網上搜到的,轉)
重載和覆寫有什麼區別?
重載有對於已有的方法或操作符進行重構,方法被重載後可以通過其重載的形式或方法原形來調用,有幾個重載就有幾個調用的形式;操作符重載後會變成你重構的定義.
而覆寫則是將之前的方法進行隱藏
重載提供了對一個方法簽名的不同參數調用的實現。
覆寫提供了子類中改變父類方法行爲的實現。
其實很本質的區別就是看函數特徵:覆寫(Override)的兩個函數的函數特徵相同,重載(Overload)的兩個函數的函數名雖然相同,但函數特徵不同。
函數特徵包括函數名,參數的類型和個數。
Override 是在繼承的時候,如果你寫的函數與要繼承的函數函數特徵相同,那麼,加上這個關鍵字,在使用這個子類的這個函數的時候就看不見父類(或超類)的函數了,它被覆蓋掉了。
比如:Derived繼承了Base,Base裏面有void A(int a)
那麼如果你Derived裏面覺得A寫得不好或不適合這個類,你想重新再寫一遍A裏的代碼,那麼就寫override void A(int a)這樣,原來的那個函數就被你新寫的這個覆蓋掉了。
Overload 是重載,就是說函數名相同,函數特徵不同,系統會根據你提供的參數來調相應的函數。
比如:void A(int a)和void A(int a,int b)
如果你用的是A(1)那麼調的是第一個,如果是A(1,1)那麼調的是第二個。
都說的好,重載和覆蓋還有個關鍵區別就是:
重載的既可以是父類的方法也可以是子類的方法(雖然名字相同但是參數不同)
而覆蓋就是在子類中定義一個和父類一樣的方法(關鍵是名字和參數都是一樣的),用中文覆蓋來說明這種現象是在好不過了。。。。。。。
重載與覆蓋
成員函數被重載的特徵:
(1)相同的範圍(在同一個類中);
(2)函數名字相同;
(3)參數不同;
(4)virtual關鍵字可有可無。
覆蓋是指派生類函數覆蓋基類函數,特徵是:
(1)不同的範圍(分別位於派生類與基類);
(2)函數名字相同;
(3)參數相同;
(4)基類函數必須有virtual關鍵字
舉例說明:
覆寫(overriding):
class A {
System.out.println("This is class A");
}
class B extends A {
System.out.println("This is class B");
}
重載(overloading):
class C {
void print(int i) {
System.out.println(i);
}
void print(float f) {
System.out.println(f);
}
}