本篇讲述虚函数与纯虚函数的区别与用法

**对于抽象类来说,它无法实例化对象,而对于抽象类的子类来说,只有把抽象类中的纯虚函数全部实现之后,那么这个子类才可以实例化对象**
1
2
3
4
5
6
7
8
9
10
class person
{
private:
int age;
bool gender;
public:
void work();
void printInfo();
};

简单理解就是父类定义了一个群体将会有的动作以及行为:如Worker类,我们仅知道工人们会工作,但是我们不知道具体是什么工人以及从事于什么样的工作,因此,可以把worker类定义为抽象类,用以规定可能会有的行为以及操作。

1
2
3
4
5
6
7
8
9
10
class workerpublic person
{
private:
int age;
bool gender;
public:
//定义为抽象基类是避免实例化造成的编译报错,并且基类的定义时1为了规定大致的行为操作,具体的内容实现是基于继承类
virtual void work() = 0;
virtual void printInfo() = 0;
};

同时,对于抽象类的子类也可以是抽象类

1
2
3
4
5
6
7
8
9
10
class dustManpublic worker
{
private:
int age;
bool gender;
public:
//定义为抽象基类是避免实例化造成的编译报错,并且基类的定义时1为了规定大致的行为操作,具体的内容实现是基于继承类
virtual void work(){cout << "扫地";}
virtual void printInfo(){cout << "我是清洁工";}
};

需要注意的是,如果基类中有纯虚函数(该类为抽象类,不能实例化对象),那么子类实现过程中必须重新定义纯虚函数,编译器才不会报错。

  1. 虚函数是动态绑定的,也就是说。使用虚函数的指针和引用能够正确找到实际类的相应函数,而不是运行定义类的函数。

    这是虚函数的基本功能,就不再解释了。

  2. 构造函数不能是虚函数。并且,在构造函数中调用虚函数,实际运行的是父类的相应函数。由于自己还没有构造好, 多态是被disable的。

  3. 析构函数能够是虚函数。并且,在一个复杂类结构中。这往往是必须的

  1. 将一个函数定义为纯虚函数。实际上是将这个类定义为抽象类,不能实例化对象

  2. 纯虚函数通常未定义体,但也全然能够拥有, 甚至能够显示调用。

  1. 析构函数能够是纯虚的,但纯虚析构函数必须有定义体,*由于析构函数的调用是在子类中隐含的*

  2. 非纯的虚函数必须有定义体,不然是一个错误。

  3. 派生类的override虚函数定义必须和父类全然一致(c++11中使用override进行编译器检查)。除了一个特例,假设父类中返回值是一个指针或引用。子类override时能够返回这个指针(或引用)的派生。

    比如,在上面的样例中,在Base中定义了 virtual Base* clone(); 在Derived中能够定义为 virtual Derived* clone()