對C++虛函數使用的深刻體會,以及覆寫,重載的區別?

虛函數就是實現函數的覆寫,

它們以下特點:

(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<*>::iterator it=m_vec.begin();it!=m_vec.end();++it)
          (
*it)->doout();
    }
    vector 
<*> 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);
  }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章