C++学习Day24z之多态

#include<iostream>
using namespace std;
/*C++中所谓的多态(polymorphism)是指,由继承而产生的相关的不同的类,其对象对同一消息会作出不同的相应
 * 多态性是面向对象程序设计的一个重要特性,能增加程序的灵活性,可以减轻系统升级,维护调试的工作量和复杂度。*/

/*多态实现的前提是赋值兼容。
 * 赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来代替,赋值兼容是一种默认行为,不需要任何的显示的转化步骤。*/

/*派生类的对象可以赋值给基类对象
 * 派生类的对象可以初始化基类的引用
 * 派生类对象的地址可以赋值给基类的指针*/

class Shape
{
public:
    Shape(int x,int y)
        :_x(x),_y(y)
    {
    
    }
    void draw()
    {
        cout<<"draw from "<<"("<<_x<<","<<_y<<")"<<endl;
    }
protected:
    int _x;
    int _y;
};

class Circle:public Shape
{
public:
    Circle(int x,int y,int r)
        :Shape(x,y),_radius(r)
    {
    
    }
    void draw()
    {
        //cout<<"draw from "<<"("<<_x<<","<<_y<<")";
        Shape::draw();
        cout<<" radius = "<<_radius<<endl;
    }

    void func()
    {
        cout<<"hahahahah 8**************"<<endl;
    }
private:
    int _radius;
};


int main()
{
    Shape s(1,2);
    s.draw();

    Circle c(3,4,5);
    c.draw();
    /*赋值兼容只发生在公有派生的父子关系中,但是你把前面改成protected就不行了
     *1.子类对象赋给父类的对象
     *2.子类对象赋给父类的引用
     *3.子类对象的地址赋给父类的指针。
     */
    //s=c 这里是把c赋值给s,然后我s.draw()
    //在替换之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员,比如这下面用s.draw()输出3,4。然后你也不能调用s.func();因为你基类里面没有这个成员。
    s=c;
    s.draw();
    //引用 
    Shape &rc=c;
    rc.draw();

    //指针
    Shape *ps=&c;
    ps->draw();
    return 0;
}


#include<iostream>
using namespace std;

/*
 *多态
 *静多态,前面学习函数重载也是一种多态现象,通过命名倾轧在编译阶段决定的,故称为静多态。静多态是在编译阶段决定的
 *动多态,是在运行时决定的。
 *动多态形成的条件有3个
 *1.父类当中有虚函数,声明虚函数的方法就是在函数前面加个virtual,但是当实现和声明分开的时候,实现的时候不用加virtual。
 *2.子类当中覆写(override)了父类的虚函数
    1.覆写的虚函数要求函数名,返回值类型,函数参数个数以及类型全部匹配
    2.子类中的覆写的函数,可以为任意访问类型,依子类需求决定
 *3.将子类对象地址赋给了父类的指针,并发生虚函数调用。
 */

class Shape
{
public:
    Shape(int x,int y)
        :_x(x),_y(y)
    {
    
    }
    virtual void draw()
    {
        cout<<" draw from "<<"("<<_x<<","<<_y<<")"<<endl;
    }
    int _x;
    int _y;
};

class Rect:public Shape
{
public:
    Rect(int x,int y,int len,int width)
        :Shape(x,y),_len(len),_width(width)
    {
    
    }
    //覆写父类里面的虚函数,加不加virtual都是一样的。
    virtual void draw();
private:
    int _len;
    int _width;
};
void Rect::draw()
{
    cout<<" star from "<<"("<<_x<<","<<_y<<") "<<"len = "<<_len<<" _width = "<<_width<<endl;
};

class Circle:public Shape
{
public:
    Circle(int x,int y,int r)
        :Shape(x,y),_radius(r)
    {
    
    }
    void draw()
    {
        cout<<" start from "<<"("<<_x<<","<<_y<<") "<<"_radius = "<<_radius<<endl;
    }
private:
    int _radius;
};

int main()
{
    Circle c(1,2,3);

    Shape *ps=&c;
    //如果没有虚函数的话应该输出(1,2);
    //但是用来虚函数之后变成(1,2,3)了
    //虽然我们在这里用了父类的指针调用了父类的虚函数,但是实际表现的是子类的
    //特性,所以这里父类只提供一个接口。
    ps->draw();
    ps=new Rect(3,4,5,6);
    ps->draw();
}

#if 0
这里C覆写了B的,但是B里面什么都没有,但是由于继承的方式也可以覆写
class A
{
public:
    virtual void func()
    {
    
    }
}

class B:public A
{

}

class C:public B
{
    virtual void func()
    {
    
    }

}
#endif #include<iostream>
using namespace std;

/*
 *多态
 *静多态,前面学习函数重载也是一种多态现象,通过命名倾轧在编译阶段决定的,故称为静多态。静多态是在编译阶段决定的
 *动多态,是在运行时决定的。
 *动多态形成的条件有3个
 *1.父类当中有虚函数,声明虚函数的方法就是在函数前面加个virtual,但是当实现和声明分开的时候,实现的时候不用加virtual。
 *2.子类当中覆写(override)了父类的虚函数
    1.覆写的虚函数要求函数名,返回值类型,函数参数个数以及类型全部匹配
    2.子类中的覆写的函数,可以为任意访问类型,依子类需求决定
 *3.将子类对象地址赋给了父类的指针,并发生虚函数调用。
 */

class Shape
{
public:
    Shape(int x,int y)
        :_x(x),_y(y)
    {
    
    }
    virtual void draw()
    {
        cout<<" draw from "<<"("<<_x<<","<<_y<<")"<<endl;
    }
    int _x;
    int _y;
};

class Rect:public Shape
{
public:
    Rect(int x,int y,int len,int width)
        :Shape(x,y),_len(len),_width(width)
    {
    
    }
    //覆写父类里面的虚函数,加不加virtual都是一样的。
    virtual void draw();
private:
    int _len;
    int _width;
};
void Rect::draw()
{
    cout<<" star from "<<"("<<_x<<","<<_y<<") "<<"len = "<<_len<<" _width = "<<_width<<endl;
};

class Circle:public Shape
{
public:
    Circle(int x,int y,int r)
        :Shape(x,y),_radius(r)
    {
    
    }
    void draw()
    {
        cout<<" start from "<<"("<<_x<<","<<_y<<") "<<"_radius = "<<_radius<<endl;
    }
private:
    int _radius;
};

int main()
{
    Circle c(1,2,3);

    Shape *ps=&c;
    //如果没有虚函数的话应该输出(1,2);
    //但是用来虚函数之后变成(1,2,3)了
    //虽然我们在这里用了父类的指针调用了父类的虚函数,但是实际表现的是子类的
    //特性,所以这里父类只提供一个接口。
    ps->draw();
    ps=new Rect(3,4,5,6);
    ps->draw();
}

#if 0
这里C覆写了B的,但是B里面什么都没有,但是由于继承的方式也可以覆写
class A
{
public:
    virtual void func()
    {
    
    }
}

class B:public A
{

}

class C:public B
{
    virtual void func()
    {
    
    }

}
#endif 


#include<iostream>
using namespace std;
#if 0
纯虚函数 格式
class 类名
{
    以前我们就是virtual函数声明就行了,但是我们这里多了个=0
    注意=0其实就是一个形式
    virtual 函数声明=0;
    纯虚函数没有实现体
    含有纯虚函数的类称为抽象基类。抽象基类不能实例化,就是你不能Shape a这种操作。它的作用就是给族类提供接口。可以被覆写
    如果一个类中声明了纯虚函数,而在派生类中没有对该函数定义,则该虚函数在派生类中仍热为纯虚函数,派生类仍然为纯虚函数
    含有虚函数的类,析构函数也应该声明为虚函数。在delete父类的时候,会调用子类的析构函数,实现完整析构。
}
#endif
class Shape
{
public:
    Shape(int x,int y)
        :_x(x),_y(y)
    {
        cout<<"Shape(int x,int y)"<<endl;
    }
    virtual ~Shape()
    {
        cout<<"~Shape()"<<endl;
    }
    virtual void draw()=0;
protected:
    int _x;
    int _y;
};

class Rect:public Shape
{
public:
    Rect(int x,int y,int len,int wid)
        :Shape(x,y),_len(len),_wid(wid)
    {
    
    }
    virtual void draw()
    {
        cout<<"Start from "<<"("<<_x<<","<<_y<<")";
        cout<<"len = "<<_len<<" width ="<<_wid<<endl;
    }
private:
    int _len;
    int _wid;
};

class Circle:public Shape
{
public:
    Circle(int x,int y,int r)
        :Shape(x,y),_radius(r)
    {
        cout<<"Circle(int x,int y,int r)"<<endl;
    }
    ~Circle()
    {
        cout<<"~Circle"<<endl;
    }
    virtual void draw()
    {
        cout<<"Start from "<<"("<<_x<<","<<_y<<")";
        cout<<"_radius "<<_radius<<endl;
    }
private:
    int _radius;
        
};

int main()
{
    //Circle c(1,2,3);
    /*这里输出的是
     *Shape(int x,int y)
      Circle(int x,int y,int r)
      Start from (1,2)_radius 3
      ~Shape()
     *因为你delete的时候只delete了Shape的析构,所以我们需要在Shape析构函数加个virtual就可以了,虚析构就一个用途就是为了析构完全(在delete 父类指针的时候,将子类对象析构完全)。这里在运行就不一样了。
     当一个类中含有虚函数的时候,请将其析构函数变成virtual。但是构造函数不是虚函数。
      virtual ~Shape();
     */
    Shape *s=new Circle(1,2,3);
    s->draw();
    delete s;
    return 0;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值