C++基础:纯虚函数和抽象类

来源:互联网 发布:开淘宝卖什么利润最高 编辑:程序博客网 时间:2024/05/21 03:26

C++基础:纯虚函数和抽象类

    纯虚函数是一种特殊的虚函数,它的一般格式如下:

    class <类名>
    {
        virtual <类型><函数名>(<参数表>)=0;
        …
    };

    在许多情况下,在基类中不能对虚函数给出有意义有实现,而把它说明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。下面给出一个纯虚函数的例子。

    #include

    class point
    {
    public:
    point(int i=0, int j=0) { x0=i; y0=j; }
    virtual void set() = 0;
    virtual void draw() = 0;
    protected:
    int x0, y0;
    };

    class line : public point
    {
    public:
    line(int i=0, int j=0, int m=0, int n=0):point(i, j)
    {
        x1=m; y1=n;
    }
    void set() { cout<<"line::set() called./n"; }
    void draw() { cout<<"line::draw() called./n"; }
    protected:
    int x1, y1;
    };

    class ellipse : public point
    {
    public:
    ellipse(int i=0, int j=0, int p=0, int q=0):point(i, j)
    {
        x2=p; y2=q;
    }
    void set() { cout<<"ellipse::set() called./n"; }
    void draw() { cout<<"ellipse::draw() called./n"; }
    protected:
    int x2, y2;
    };

    void drawobj(point *p)
    {
    p->draw();
    }

    void setobj(point *p)
    {
    p->set();
    }

    void main()
    {
    line *lineobj = new line;
    ellipse *elliobj = new ellipse;
    drawobj(lineobj);
    drawobj(elliobj);
    cout<
    setobj(lineobj);
    setobj(elliobj);
    cout<<"/nRedraw the object.../n";
    drawobj(lineobj);
    drawobj(elliobj);
    }

    抽象类

    带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。

    抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。

    抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。

    抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。 

 

 

在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

一、定义.

纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

virtual void funtion1()=0

二、引入原因:

1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重载以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。

三、相似概念:

1、多态性

指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。

a.编译时多态性:通过重载函数实现

b 运行时多态性:通过虚函数实现。

2、虚函数

虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态重载

3、抽象类

包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。

程序举例:

基类:
class A 
{
public:
A();
void f1();
virtual void f2();
virtual void f3()=0;
virtual ~A();

};

子类:
class B : public A 
{
public:
B();
void f1();
void f2();
void f3();
virtual ~B();

};
主函数:
int main(int argc, char* argv[])
{
A *m_j=new B();
m_j->f1();
m_j->f2();
m_j->f3();
delete m_j;
return 0;
}

f1()是一个普通的重载.
调用m_j->f1();会去调用A类中的f1(),它是在我们写好代码的时候就会定好的.
也就是根据它是由A类定义的,这样就调用这个类的函数.
f2()是虚函数.
调用m_j->f2();会调用m_j中到底保存的对象中,对应的这个函数.这是由于new的B
对象.
f3()与f2()一样,只是在基类中不需要写函数实现.

 抽象就是把有共同属性或方法的抽象成一个类

实现不了自己定义的接口(纯虚函数)就是抽象类。反过来想。如:我们定义了动物的类,属性是有嘴,方法是 吃。我们没有定义吃的具体实现。在派生类 老虎里 定义了 吃的 具体实现  吃肉,派生类 牛 里定义了 吃 的 具体实现 吃草,这就说明动物这个类 是抽象类,决定不了吃的具体实现,必须实现了吃 这个接口的类才不是抽象的类。如果实现了 吃的方法,那动物这个类就不能就不能通过接口说明 它是个抽象类。

 定义纯虚函数就是把派生类里的共同的方法抽象出来放到基类里,但并没有具体实现(描述)(因为是抽象的无法具体描述对象),派生类里对这些共同的方法来描述。如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。把’吃肉‘,’吃草‘的共同方法’吃‘提取出来,那么动物就是抽象类。

将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的版本决不会调用。

为什么说只要拥有纯虚函数的类就是抽象类?

派生类能够描述对象的信息,而基类类却不能描述此类对象的信息(即纯虚函数),就是抽象类。

抽象类定义是对象有共同属性或方法抽象成一个类,但无法描述具体的对象(肯定无法描述),它是不存在的

首先 基类里 存在着派生类的 共同的属性 方法,但是如果是虚函数的话,基类的方法就和派生不一样了,因为虚函数是动态绑定,它改写基类的虚函数后,就与基类的实现不同了,这样基类就没有提取派生类的共同方法,基类也不是抽象类。如果定义为纯虚函数,则基类的纯虚函数就是个接口,纯虚函数不能被调用,它的存在只是为了在派生类中重新定义。通过纯虚函数的定义来确定抽象类以区别具体类。(同样的方法因为派生类能够调用而基类不能调用,所以是抽象类)抽象类也就是无法实例化。

原创粉丝点击