基类指针和派生类指针
Posted zhanghuan_wangkai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基类指针和派生类指针相关的知识,希望对你有一定的参考价值。
基类指针指向派生类对象
派生类对象也“是”基类对象,但两者不同。
派生类对象可以当做基类对象,这是因为派生类包含基类的所有成员。
但是基类对象无法被当做成派生类对象,因为派生类可能具有只有派生类才有的成员。
所以,将派生类指针指向基类对象的时候要进行显示的强制转换,否则会使基类对象中的派生类成员成为未定义的。
总结:基类指针和派生类指针指向基类对象和派生类对象的4中方法:
1. 基类指针指向基类对象,简单。只需要通过基类指针简单地调用基类的功能。
2. 派生类指针指向派生类对象,简单。只需要通过派生类指针简单地调用派生类功能。
3. 将基类指针指向派生类对象是安全的,因为派生类对象“是”它的基类的对象。
但是要注意的是,这个指针只能用来调用基类的成员函数。
如果试图通过基类指针调用派生类才有的成员函数,则编译器会报错。
为了避免这种错误,必须将基类指针强制转化为派生类指针。然后派生类指针可以用来调用派生类的功能。这称为向下强制类型转换,这是一种潜在的危险操作。
注意:如果在基类和派生来中定义了虚函数(通过继承和重写),并同过基类指针在派生类对象上调用这个虚函数,则实际调用的是这个函数的派生类版本。
4. 将派生类指针指向基类对象,会产生编译错误。“是”关系只适用于从派生类到它的直接(或间接)基类,反过来不行。
基类对象并不包含派生类才有的成员,这些成员只能通过派生类指针调用。
先上一段代码:
[cpp] view plain copy
- #include <iostream>
- using namespace std;
- //没有使用虚函数的继承派生关系
- class Base
- public:
- Base(int i = 0):ival(i)
- void getVal()
- cout<<ival<<endl;
- private:
- int ival;
- ;
- class Derived:public Base
- public:
- Derived(int i = 0, int j = 1):Base(i),ival(j)
- void getVal()
- cout<<ival<<endl;
- private:
- int ival;
- ;
- //使用了虚函数的继承派生关系
- class Base1
- public:
- Base1(int i = 0):ival(i)
- virtual void getVal()
- cout<<ival<<endl;
- private:
- int ival;
- ;
- class Derived1:public Base1
- public:
- Derived1(int i = 0, int j = 1):Base1(i),ival(j)
- void getVal()
- cout<<ival<<endl;
- private:
- int ival;
- ;
- void useBaseObj(Base b)
- b.getVal();
- void useDerivedObj(Derived d)
- d.getVal();
- void useBasePtr(Base *pb)
- pb->getVal();
- void useDerivedPtr(Derived *pd)
- pd->getVal();
- void useBase1Obj(Base1 b)
- b.getVal();
- void useDerived1Obj(Derived1 d)
- d.getVal();
- void useBase1Ptr(Base1 *pb)
- pb->getVal();
- void useDerived1Ptr(Derived1 *pd)
- pd->getVal();
- int main()
- Base b;
- Derived d;
- Base *pb = &b;
- Derived *pd = &d;
- useBaseObj(b);//基类实参,基类形参,调用基类函数
- useBaseObj(d);//派生类实参,基类形参,自动转化,调用基类函数
- // useDerivedObj((Derived)b);//无法用基类(自动的)构造出一个派生类
- useDerivedObj(d);//派生类实参,派生类形参,调用派生类函数
- cout<<endl;
- useBasePtr(pb);//指向基类形参,指向基类实参,调用基类函数
- useBasePtr(pd);//指向基类形参,指向派生类实参,调用静态类型-基类函数
- // useDerivedPtr(pb);//指向基类实参,指向派生类形参,无法自动转化
- useDerivedPtr((Derived*)pb);//强制类型转化,打印结果为随机数
- //为什么?
- //因为程序试图访问一个自己并没有的成员
- useDerivedPtr(pd);//指向派生类实参,指向派生类形参,调用派生类
- cout<<endl;
- pb = new Derived;//静态类型为指向基类,动态类型为指向派生类
- useBasePtr(pb);//形参为指向基类指针,实参静态类型为指向基类指针,调用基类函数
- useDerivedPtr((Derived*)pb);//形参类型为指向派生类指针,实参静态类型为指向基类的指针
- //但是由于内存中的确有这个数(因为我们实际new的是一个派生类)
- //所以结果为派生类函数
- cout<<endl;
- 基类指针和派生类指针