再論虛函數!

來源:互聯網
上載者:User

鄙人愚笨,看C++2月了 對於虛函數 還是不能深刻理解,今特寫些東西,再學習一下。

程式:

#include"iostream"
using namespace std;
class A{
public:
 A(int i):a(i)  {cout<<"調用建構函式A "<<endl;}
 void showa(){cout<<a<<"haha"<<endl;}
 void showw(){cout<<"A::"<<endl;}//只有虛函數才能=0
  ~A(){cout<<"析構A"<<endl;};
protected:int a;

};

class B:public  A//virtual public A
{
public:B(int x,int y):A(x),j(y){cout<<"調用建構函式B "<<endl;}
 void showb(){cout<<a<<" "<<j<<endl;}
 void showw(){cout<<"B::"<<endl;}//刪掉詞句,也能輸出C::,說明虛函數能繼承哦
 ~B(){cout<<"析構B"<<endl;}
protected:int j;
};
class D
{
public:D(){cout<<"構造D"<<endl;}
    virtual void showd(){cout<<"d的值"<<endl;}
    void showw(){cout<<"D::"<<endl;}
    ~D(){cout<<"析構D";}

};

class C:public  B, public  A,public D//virtual public A

{
public:
    C(int x,int y,int z):B( x, y),A(y),k(z)

    {cout<<"調用建構函式C "<<endl;}
    void showc(){cout<<"B::a="<<B::a<<"  "<<"A::a="<<A::a<<"  "<<j<<"  "<<k<<endl;}
  void showw(){cout<<"C::"<<endl;}
  void showd(){cout<<"CD::"<<endl;}
  ~C(){cout<<"析構C";}
private:int k;

};
int main()
{
C c(1,2,3);
c.showw();
return 0;
}

四個類裡面都有函數showw(),程式當然不會報錯了,因為繼承嘛。此程式的輸出是C::,說明在沒有指定域的情況下,預設的是衍生類別的函數哦!

當然有個警告: warning C4584: “C”: 基類“A”已是“B”的基類
1>        f:\c++\vs2008\asd\asd\adw.cpp(5) : 參見“A”的聲明
1>        f:\c++\vs2008\asd\asd\adw.cpp(15) : 參見“B”的聲明

我想:是因為A其實有兩份拷貝,也就是A-B-C和A-C。我試了下把A定義成虛基類,也就是弄成一份拷貝,警告消失。具體見注釋!

 

現在把基類A裡的showw()弄成虛函數。如下

#include"iostream"
using namespace std;
class A{
public:
 A(int i):a(i)  {cout<<"調用建構函式A "<<endl;}
 void showa(){cout<<a<<"haha"<<endl;}
 virtual void showw(){cout<<"A::"<<endl;}//只有虛函數才能=0
  ~A(){cout<<"析構A"<<endl;};
protected:int a;

};

class B:public  A//virtual public A
{
public:B(int x,int y):A(x),j(y){cout<<"調用建構函式B "<<endl;}
 void showb(){cout<<a<<" "<<j<<endl;}
 void showw(){cout<<"B::"<<endl;}//刪掉詞句,也能輸出C::,說明虛函數能繼承哦
 ~B(){cout<<"析構B"<<endl;}
protected:int j;
};
class D
{
public:D(){cout<<"構造D"<<endl;}
    virtual void showd(){cout<<"d的值"<<endl;}
    void showw(){cout<<"D::"<<endl;}
    ~D(){cout<<"析構D";}

};

class C:public  B, public  A,public D//virtual public A

{
public:
    C(int x,int y,int z):B( x, y),A(y),k(z)

    {cout<<"調用建構函式C "<<endl;}
    void showc(){cout<<"B::a="<<B::a<<"  "<<"A::a="<<A::a<<"  "<<j<<"  "<<k<<endl;}
  void showw(){cout<<"C::"<<endl;}
  void showd(){cout<<"CD::"<<endl;}
  ~C(){cout<<"析構C";}
private:int k;

};
int main()
{
C c(1,2,3);
c.showw();
return 0;
}

main函數不變,輸出一模一樣,我的理解是:如果虛函數不利用衍生類別的引用或是地址,也就跟普通函數一樣了,不知道正確否,反正偵錯工具,沒發現異樣!

把主函數變下:

int main()
{
C c(1,2,3);
A *a=&c;

a->showw();

  }根據結果,輸出的是C的showw(),當然很容易理解,正是虛函數的意義嘛。也可以調用a->A::showw(),輸出的就是A的showw().

再加句:a->showc();報錯,原因很簡單,此函數不是a的成員。

到此,我想大體虛函數的怎麼用可能會一點點,而其真正的意義呢?讀書求甚解。

 

把B類的showw()刪了,運行

結果正常跟沒刪一樣,因為B繼承了A的showw(),還是用程式說話吧。

改寫main

C c(1,2,3);

B *b=&c;

b->B::showw();//輸出A::

b->showw();//輸出C::

輸出是C的showw() 說明了B確實繼承了A 的showw() ,並且還是虛擬。虛擬函數可以繼承,實至名歸。

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.