20140424 父類指針指向子類 子類指針指向父類 父類指針不能訪問子類成員(虛函數例外)


1、父類指針指向子類

B b;   A *pa;   pa=&b;//A為父類,B為子類

第一步:子類對象指針&b隱式轉換為父類指針

第二步:將轉換后的得到的父類指針賦值給pa

2、子類指針指向父類(父類A,子類C)

第一步:父類指針轉換為子類時

               假如用pc=dynamic_cast<C *>(pa),則父類A必須必須要有虛函數,轉換時會根據pa的具體指向進行判斷(動態轉換體現於此,如果pa沒有指向C類型,結果返回0)。

               假如用pc=static_cast<C *>(pa),則父類A必須不需要有有虛函數,轉換時不會判斷pa的指向(即使pa沒有指向C,轉換照樣成功,見以下程序2處

第二步:將轉換后的得到的子類指針賦值給pc

例子:

#include<iostream>
using namespace std;
class A
{
public:
    virtual void fa()
    {
        cout<<"使用dynamic_cast將父類指針轉換為子類時,父類必須要有虛函數,此時父類才是多態類型"<<endl;
    }
};

class B:public A
{

};
class C: public A
{

};

void main()
{
    A a;    B b;    C c;
    A *pa; B *pb; C *pc;
    pa=&b;
    pa->fa();
    cout<<dynamic_cast<B *>(pa)<<endl;//1、父類指針A轉化為子類B,因為pa指向b,所以打印出0038FA70
    cout<<dynamic_cast<C *>(pa)<<endl;//2、父類指針A轉化為子類C,因為pa沒有指向C,所以打印出00000000 (和1比較)
    cout<<static_cast<C *>(pa)<<endl;//3、父類指針A轉化為子類指針C,雖然pa沒有指向C,但是這里用static_cast,所以打印出0038FA70(和2比較)
    pb=dynamic_cast<B *>(&a);//父類指針轉換為子類指針,因為&a並不是B類型,轉換失敗,所以打印出00000000()
    cout<<dynamic_cast<B *>(&a)<<endl;
}

 

3、父類指針不能訪問子類數據成員

class a 
{public: 
int aa}; 
class b:public a 
{public: 
int bb; 

從內存的來看 
如a 
---------| 
|占一個int數據大小--| 
|----(aa數據)------| 
|--------- 
而b則是 
---------|--------- 
|占一個int數據大小--|占一個Int數據大小--| 
|從a中繼承而來------|---(bb數據----------| 
|------------------ 
當定義一個基類類型的指針時 
a *p;這時,這個指針指向的是a類型的數據 
當p指針指向派生類的時候,因為p是a類型的指針,所以*p只解釋為a類型數據的長度,即 
————————-|--------- 
|占一個int數據大小--|占一個Int數據大小--| 
|從a中繼承而來------|-----(bb數據)-------| 
|------------------ 
|------------|----------| 
|-p只指向這個區域_--| 
總結

  • 當基類的指針(P)指向派生類的時候,只能操作派生類中從基類中繼承過來的數據
  • 指向派生類的指針,因為內存空間比基類長,會導致嚴重了后果,所以不允許派生類的指針指向基類。而基類的指針可以指向派生類。(見以下代碼)
  • C++的多態性(虛函數)能解決基類指針不能操作派生類的數據成員的問題。    

 

#include<iostream>
using namespace std;
class A  
{
public:  
int aa;
};  

class B:public A  
{public:  
int bb;  
};

void main()
{
    A *pa;
    B bb;
    bb.aa=1;
    bb.bb=2;
    pa=&bb;
    
    cout<<pa<<endl;  
    cout<<(B*)(pa)<<endl;
    cout<(B*)(pa)->aa;//可以訪問
    cout<<static_cast<B*>(pa)->aa<<endl;
    //cout<(B*)(pa)->bb;//普通的強制類型轉換,不可以訪問子類成員bb
    cout<<static_cast<B*>(pa)->bb<<endl;//用了static_cast轉換之后,子類成員bb就可以訪問了
}

  

 

用C++比較好說明白:       
  1:指針的可訪問性是由指針的定義決定的,比如說用BaseClass定義的指針,可訪問的范圍就是BaseClass的內存區域       
  2:允許用一個指向基類的指針指向派生類,由於被指向的對象(子類)的內存空間大於指針(父類)的可訪問空間,所以這種向上映射(子類轉化為父類)是安全的       
  3:對象在調用虛函數的時候,是調用父類的函數還是調用派生類的函數,是和對象的類型有關的,比如說一個派生類B,其父類是A,則B的對象調用父類中被聲明為VIRTUAL的函數時,被B   所OVERRIDE的函數調用的是B里的函數,而B沒有OVERRIDE的函數調用的是基類里的函數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM