基类指针和派生类指针

Posted zhanghuan_wangkai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基类指针和派生类指针相关的知识,希望对你有一定的参考价值。

基类指针指向派生类对象

派生类对象也“是”基类对象,但两者不同。

派生类对象可以当做基类对象,这是因为派生类包含基类的所有成员。

但是基类对象无法被当做成派生类对象,因为派生类可能具有只有派生类才有的成员。

所以,将派生类指针指向基类对象的时候要进行显示的强制转换,否则会使基类对象中的派生类成员成为未定义的。

总结:基类指针和派生类指针指向基类对象和派生类对象的4中方法:

1.  基类指针指向基类对象,简单。只需要通过基类指针简单地调用基类的功能。

2.  派生类指针指向派生类对象,简单。只需要通过派生类指针简单地调用派生类功能。

3.  将基类指针指向派生类对象是安全的,因为派生类对象“是”它的基类的对象。

但是要注意的是,这个指针只能用来调用基类的成员函数。

如果试图通过基类指针调用派生类才有的成员函数,则编译器会报错。

为了避免这种错误,必须将基类指针强制转化为派生类指针。然后派生类指针可以用来调用派生类的功能。这称为向下强制类型转换,这是一种潜在的危险操作。

注意:如果在基类和派生来中定义了虚函数(通过继承和重写),并同过基类指针在派生类对象上调用这个虚函数,则实际调用的是这个函数的派生类版本。

4.  将派生类指针指向基类对象,会产生编译错误。“是”关系只适用于从派生类到它的直接(或间接)基类,反过来不行。

 基类对象并不包含派生类才有的成员,这些成员只能通过派生类指针调用。



先上一段代码:

[cpp]  view plain  copy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. //没有使用虚函数的继承派生关系  
  5. class Base  
  6.   
  7. public:  
  8.     Base(int i = 0):ival(i)  
  9.     void getVal()  
  10.       
  11.         cout<<ival<<endl;  
  12.       
  13. private:  
  14.     int ival;  
  15. ;  
  16.   
  17. class Derived:public Base  
  18.   
  19. public:  
  20.     Derived(int i = 0, int j = 1):Base(i),ival(j)  
  21.     void getVal()  
  22.       
  23.         cout<<ival<<endl;  
  24.       
  25. private:  
  26.     int ival;  
  27. ;  
  28.   
  29. //使用了虚函数的继承派生关系  
  30. class Base1  
  31.   
  32. public:  
  33.     Base1(int i = 0):ival(i)  
  34.     virtual void getVal()  
  35.       
  36.         cout<<ival<<endl;  
  37.       
  38. private:  
  39.     int ival;  
  40. ;  
  41.   
  42. class Derived1:public Base1  
  43.   
  44. public:  
  45.     Derived1(int i = 0, int j = 1):Base1(i),ival(j)  
  46.     void getVal()  
  47.       
  48.         cout<<ival<<endl;  
  49.       
  50. private:  
  51.     int ival;  
  52. ;  
  53.   
  54.   
  55. void useBaseObj(Base b)  
  56.   
  57.     b.getVal();  
  58.   
  59.   
  60. void useDerivedObj(Derived d)  
  61.   
  62.     d.getVal();  
  63.   
  64.   
  65. void useBasePtr(Base *pb)  
  66.   
  67.     pb->getVal();  
  68.   
  69.   
  70. void useDerivedPtr(Derived *pd)  
  71.   
  72.     pd->getVal();  
  73.   
  74.   
  75. void useBase1Obj(Base1 b)  
  76.   
  77.     b.getVal();  
  78.   
  79.   
  80. void useDerived1Obj(Derived1 d)  
  81.   
  82.     d.getVal();  
  83.   
  84.   
  85. void useBase1Ptr(Base1 *pb)  
  86.   
  87.     pb->getVal();  
  88.   
  89.   
  90. void useDerived1Ptr(Derived1 *pd)  
  91.   
  92.     pd->getVal();  
  93.   
  94.   
  95. int main()  
  96.   
  97.     Base b;  
  98.     Derived d;  
  99.   
  100.     Base *pb = &b;  
  101.     Derived *pd = &d;  
  102.     useBaseObj(b);//基类实参,基类形参,调用基类函数  
  103.     useBaseObj(d);//派生类实参,基类形参,自动转化,调用基类函数  
  104. //  useDerivedObj((Derived)b);//无法用基类(自动的)构造出一个派生类  
  105.     useDerivedObj(d);//派生类实参,派生类形参,调用派生类函数  
  106.     cout<<endl;  
  107.   
  108.     useBasePtr(pb);//指向基类形参,指向基类实参,调用基类函数  
  109.     useBasePtr(pd);//指向基类形参,指向派生类实参,调用静态类型-基类函数  
  110. //  useDerivedPtr(pb);//指向基类实参,指向派生类形参,无法自动转化  
  111.     useDerivedPtr((Derived*)pb);//强制类型转化,打印结果为随机数  
  112.                                 //为什么?  
  113.                                 //因为程序试图访问一个自己并没有的成员  
  114.     useDerivedPtr(pd);//指向派生类实参,指向派生类形参,调用派生类  
  115.     cout<<endl;  
  116.   
  117.     pb = new Derived;//静态类型为指向基类,动态类型为指向派生类  
  118.     useBasePtr(pb);//形参为指向基类指针,实参静态类型为指向基类指针,调用基类函数  
  119.     useDerivedPtr((Derived*)pb);//形参类型为指向派生类指针,实参静态类型为指向基类的指针  
  120.                                 //但是由于内存中的确有这个数(因为我们实际new的是一个派生类)  
  121.                                 //所以结果为派生类函数  
  122.     cout<<endl;  
  123. 基类指针和派生类指针

    基类指针指向派生类对象&派生类指针指向基类对象

    虚函数和基类中的this指针的问题!

    派生类和基类的转换

    使用具有指向派生类对象的指针的基类指针数组调用派生类方法

    知道基类指针指向哪个派生类