(转)基类指针与派生类指针

来源:互联网 发布:服装设计师软件 编辑:程序博客网 时间:2024/04/30 10:53

#include<iostream.h>
#include<iomanip.h>
class Point
{
    friend ostream &operator<<(ostream &,const Point &);
    public:
        Point(int =0,int =0);
        void setPoint(int,int);
        int getX() const {return x;}
        int getY() const {return Y;}
    protected:
        int x;
        int y;
};
ostream &operator<<(ostream &,const Point &p)
{
output<<'['<<p.x<<','<<p.y<<']';
return output;
}
class Circle:public Point
{
friend ostream &operator<<(ostream &,const Circle &);
    public:
   Circle(double r=0.0,int x=0,int y=0);
   void setRadius(double);
   double getRadius() const;
   double area() const;
protected:
   double Radius;
};
friend ostream &operator<<(ostream &,const Circle &c)
{
output<<"Center="<<static_cast<Point>(c)
    <<",Radius="
    <<setiosflags(ios::fixed|ios:showpoint)
    <<setprecision(2)<<c.radius;
return output;
}
int main()
{
Point *pointPtr=0,p(30,50);
Circle *circlePtr=0,c(2.7,120,89);

cout<<"Point p:"<<p<<"/nCircle c:"<<c<<endl;

pointPtr=&c;
cout<<"/nCircle c (via *pointPtr):"
   <<*pointPtr<<endl;

    pointPtr=&c;

circlePtr=static_cast<Circle *>(pointPtr);
cout<<"/nCircle c (via *circlePtr):/n"<<*circlePtr
   <<"/nArea of c (via circlePtr)"
   <<circlePtr->area()<<endl;

pointPtr=&p;

    circlePtr=static_cast<Circle *>(pointPtr);
cout<<"/nPoint p (via *circlePtr)/n"<<*circlePtr
   <<"/nArea of object circlePtr points to:"
   <<circlePtr->area()<<endl;
return 0;
}

 

输出结果:

Point p:[30,50]
Circle c: Center=[120,89];Radius=2.70

Circle c (via *pointPtr):[120,89]

Circle c (via *circlePtr);
Center=[120,89];Radius=2.70
Area of c (via circlePtr):22.90

Point p(via *circlePtr);
Center=[30,50];Radius=0.00
Area of object circlePtr points to:0.00

旨在理解,省略了大部分定义的实现。个人认为理解基类指向派生类的指针,派生类指向基类的指针,以及将派生类指针强制转换为基类指针和将基类指针强制转换为派生类指针的问题,只要理解一点,那就是无论是基类指向派生类还是派生类指向基类,重点就是哪个类的指针就调用哪个类的方法,而输出的是指针指向的对象。

不怕大家笑话,打个比方先:A组有两个画家A1,A2,B组也有两个画家B1,B2,假设A组为“基类”,B组为“派生类”,A1可以画B1的肖像(就好比A1是基类指针,B1是派生类对象,A1只要看向B1即可,就好像指针的“指向”,怎么画是由A1决定的,而画的是什么是由B1决定的);B2也可以画A2的(派生类指向基类);当然A1也可以画A2的,只要A1作A组的指针,A2作A组的对象就行了。

基类定义的指针为基类指针,派生类定义的为派生类指针(废话:-))。基类指向派生类的指针即将派生类对象赋给基类指针,如果输出的话,调用的方法是基类的方法,输出的是基类在派生类中的成员(想要通过基类指针调用那些只有派生类才有的成员将会产生语法错误)。而派生类指向基类的指针即将基类对象赋给派生类指针,调用的是派生类的方法,输出的是基类对象的成员,如此例中的Center=[30,50];Radius=0.00这一行,即是派生类指向基类的指针的输出结果,调用的是派生类的<<(派生类定义的重载),想要输出Radius,而基类对象中不存在此项,所以输出0.00(其实输出的是任意的,只不过这里刚好为0)。

还有一点就是把基类指针直接赋给派生类指针是危险的,编译器不允许真么做,也不会作隐式转换,显示调用说明程序员已经知道了这种危险性。用派生类指针引用基类对象是个语法错误,如果非要这么做的话,必须像程序中那样,先用基类指针指向基类对象,再将基类指针强制转换为派生类指针。正确使用指针是程序员的责任,因此编译器允许有危险的转换。如Center=[30,50];Radius=0.00,访问不存在的数据成员是很危险的,而调用不存在的成员函数可能使程序崩溃。