C++基础#9:纯虚函数和抽象类的用法

1. 纯虚函数和抽象类的基本概念:
(1)含有纯虚函数的类是抽象类,不能生成对象,只能派生。他派生的类的纯虚函数没有被改写,那么,它的派生类还是个抽象类。
(2)定义纯虚函数就是为了让基类不可实例化化,因为实例化这样的抽象数据结构本身并没有意义.或者给出实现也没有意义。

纯虚函数是函数,而且是某个类的成员函数;

抽象类是类,而且是含有纯虚函数的类。


2.  纯虚函数的定义:
在许多情况下,在基类中不能给出有意义的虚函数定义,这时可以把它说明成纯虚函数,把它的定义留给派生类来做。定义纯虚函数的一般形式为:
class 类名{
 virtual 返回值类型 函数名(参数表)= 0;  // 后面的"= 0"是必须的,否则,就成虚函数了
};
纯虚函数是一个在基类中说明的虚函数,它在基类中没有定义,要求任何派生类都定义自己的版本。纯虚函数为各派生类提供一个公共界面。

从基类继承来的纯虚函数,在派生类中仍是虚函数。

3. 抽象类:
(1). 如果一个类中至少有一个纯虚函数,那么这个类被称为抽象类(abstract class)。
抽象类中不仅包括纯虚函数,也可包括虚函数。抽象类中的纯虚函数可能是在抽象类中定义的,也可能是从它的抽象基类中继承下来且重定义的。

(2). 抽象类特点,即抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例。
一个抽象类不可以用来创建对象,只能用来为派生类提供一个接口规范,派生类中必须重载基类中的纯虚函数,否则它仍将被看作一个抽象类。

(3). 在effective c++上中提到,纯虚函数可以被实现(定义),但是,不能创建对象实例,这也体现了抽象类的概念。

4. 虚析构函数:

虚析构函数: 在析构函数前面加上关键字virtual进行说明,称该析构函数为虚析构函数。

虽然构造函数不能被声明为虚函数,但析构函数可以被声明为虚函数。

一般来说,如果一个类中定义了虚函数, 析构函数也应该定义为虚析构函数。

例如:

class B
{
  virtual ~B();  //虚析构函数
  …
};

/*关于更多的精彩解释,请参考<< c++编程思想 >> 一书。*/
 

5. 例子:抽象类的定义和使用:

/*抽象类举例*/

#include <stdio.h>

class Animal
{
      public:
             virtual void shout() = 0;
             virtual void impl() = 0;
             virtual ~Animal() {printf(" Animal destory! /n");};   // 虚析构函数
};

void Animal::impl()        // 纯虚函数也可以被实现。
{
     printf(" Animal: I can be implement! /n");
}

class Dog: public Animal
{
      public:
             virtual void shout() // 必须要被实现,即使函数体是空的
             {
                 printf(" wang! wang! wang! /n");
             }
             virtual void impl()
             {
                 printf(" implement of Dog!  /n");
             }
             virtual ~Dog() {printf(" Dog destory! /n");};   // 虚析构函数
};

class Cat: public Animal
{
      public:
             virtual void shout() // 必须要被实现,即使函数体是空的
             {
                 printf(" miao! miao! miao! /n");
             }
            
             virtual void impl()
             {
                 printf(" implement of Cat!  /n");
             }
             virtual ~Cat() {printf(" Cat destory! /n");};   // 虚析构函数
};

/*
Animal f()  // error, 抽象类不能作为返回类型
{
      
}

void display( Animal a) //error, 抽象类不能作为参数类型
{
    
}
*/

//ok,可以声明抽象类的引用
Animal &display(Animal &a)
{
       Dog d;
       Animal &p = d;
       return p;
      
}

void test_func()
{
     //Animal a;  // error: 抽象类不能建立对象
    
    Dog dog;   //ok,可以声明抽象类的指针
    Cat cat;   //ok,可以声明抽象类的指针
   
   
    Animal *animal = &dog;
    animal->shout();
    animal->impl();
   
    printf("/n");
   
   
    animal = &cat;
    animal->shout();
    animal->impl();
   
    printf("/n");
}

int main()
{
    test_func();

    while(1);
   
    
}
/* result:
     wang! wang! wang!              
     implement of Dog! 
 
     miao! miao! miao!
     implement of Cat!
 
     Cat destory!
     Animal destory!
     Dog destory!
     Animal destory!
 
 
*/

代码说明:

void display( Animal a) //error,

编译错误,抽象类不能作为参数类型。

 

Animal a;  // error:

编译错误,抽象类不能建立对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值