c++中的抽象概念详解
一、定义.
在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的, 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类 。纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”。
virtual void funtion1()=0
二、引入原因:
1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数,则编译器要求在派生类中必须予以重载以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。
三、相似概念:
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()一样,只是在基类中不需要写函数实现.
五、总结
抽象就是把有共同属性或方法的抽象成一个类实现不了自己定义的接口(纯虚函数)就是抽象类。反过来想。如:我们定义了动物的类,属性是有嘴,方法是 吃。我们没有定义吃的具体实现。在派生类 老虎里 定义了 吃的 具体实现 吃肉,派生类 牛 里定义了 吃 的 具体实现 吃草,这就说明动物这个类 是抽象类,决定不了吃的具体实现,必须实现了吃 这个接口的类才不是抽象的类。如果实现了 吃的方法,那动物这个类就不能就不能通过接口说明 它是个抽象类。
定义纯虚函数就是把派生类里的共同的方法抽象出来放到基类里,但并没有具体实现(描述)(因为是抽象的无法具体描述对象),派生类里对这些共同的方法来描述。如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。把’吃肉‘,’吃草‘的共同方法’吃‘提取出来,那么动物就是抽象类。
将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的版本决不会调用。
为什么说只要拥有纯虚函数的类就是抽象类?
派生类能够描述对象的信息,而基类类却不能描述此类对象的信息(即纯虚函数),就是抽象类。
抽象类定义是对象有共同属性或方法抽象成一个类,但无法描述具体的对象(肯定无法描述),它是不存在的
首先基类里 存在着派生类的 共同的属性 方法,但是如果是虚函数的话,基类的方法就和派生不一样了,因为虚函数是动态绑定,它改写基类的虚函数后,就与基类的实现不同了,这样基类就没有提取派生类的共同方法,基类也不是抽象类。如果定义为纯虚函数,则基类的纯虚函数就是个接口,纯虚函数不能被调用,它的存在只是为了在派生类中重新定义。通过纯虚函数的定义来确定抽象类以区别具体类。(同样的方法因为派生类能够调用而基类不能调用,所以是抽象类)抽象类也就是无法实例化。