1. 程式人生 > >關於C++的子類指標指向父類

關於C++的子類指標指向父類

 

1,直接用基類指標引用基類物件
2,直接用派生類指標引用派生類物件
3,用基類指標引用一個派生類物件,由於派生類物件也是基類的物件,所以這種引用是安全的,
但是隻能引用基類成員。若試圖通過基類指標引用那些只在派生類中才有的成員,編譯器會報告語法錯誤。(解決該問題的答案是虛擬函式和多型性)
4,用派生類指標引用基類的物件。這種引用方式會導致語法錯誤。派生類指標必須先強制轉換為基類指標,這種方法是不安全的。 

而在侯捷的深入淺出MFC中第二章C++重要性質中:
1、如果你以一個"基類之指標"指向一個"派生類之物件",那麼經由該指標你只能呼叫該基類所定義的函式
2、如果你以一個“派生類之指標”指向一個“基類之物件”,你必須先做明顯的轉型操作(explicit cast),這種作法很危險。
3、如果基類和派生類都定義了“相同名稱之函式”,那麼通過物件指標呼叫成員函式時,到底呼叫了那個函式,必須視該指標的原始型別而定,而不是視指標實際所指的物件的型別而定,這與第1點其實意義相通。

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <stdlib.h>  
  3. using namespace std;  
  4. class A  
  5. {  
  6. public:  
  7.   char
     str[20];  
  8.   void f(){cout<<"class A"<<endl;}  
  9.   void fff(){cout<<"class A's str "<<str<<endl;}   
  10.   void add(){cout<<"class A address: "
    <<this<<endl;}  
  11. };  
  12. class B:public A  
  13. {  
  14. public:  
  15.   int i;  
  16.   char sb[20];  
  17.   B(){cout<<"class B constructor is run."<<endl;}  
  18.   ~B(){cout<<"class B destructor is run."<<endl;}  
  19.   void f(){cout<<"class B"<<endl;}  
  20.   void ff(){cout<<"class B "<<i<<str<<sb<<endl;}  
  21.   void add(){cout<<"class B address: "<<this<<endl;}  
  22. };  
  23. int main(int argc, char *argv[])  
  24. {  
  25.   //宣告父類物件  
  26.   A b;  
  27.   //宣告父類物件的指標,指向父類物件  
  28.   A *pa=&b;  
  29.   pa->add();  
  30.   //這個寫法正確,不過很危險,因為pa到底是指向B還是A是不確定的.如果能明確的知道  
  31.   //pa是指向B類物件的,就如現在寫的這個,那麼沒問題,如果pa指向A類物件,就會存在  
  32.   //風險.改變指標的型別,並不會影響記憶體分配既不會呼叫建構函式  
  33.   B *pb=(B *)pa;  
  34.   //型別強制轉化後,指向的地址相同. 但會按轉化型別訪問資料成員.  
  35.   //成員函式屬於類而不屬於物件.各物件共用類的成員函式.強制轉換成 B 型別後,可  
  36.   //呼叫類的成員函式。編譯pb->add();後的程式碼只是呼叫add函式的時候傳入了pb的對  
  37.   //象指標this  
  38.   pb->add();  
  39.   //由於pa指向的是父類物件的地址,這個指標被強制轉換為派生類指標後,會出現記憶體越  
  40.   //界訪問的情況,是不安全的.  
  41.   pb->i=100;  
  42.   char dsd[100];  
  43.   strcpy(pb->sb, " class B's sb.");  
  44.   strcpy(pb->str, " class A's str.");  
  45.   //pb->f()呼叫的具體函式,視指標的原始型別而定,而不是視指標實際所指的物件的  
  46.   //型別而定.如果是虛擬函式,則視實際所指的物件的型別而定  
  47.   pb->f();  
  48.   pb->ff();  
  49.   pb->fff();  
  50.   system("PAUSE");  
  51.   return 0;  
  52. }  
  53.