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的函數調用的是基類里的函數