C++ virtual关键字

发布时间 2023-09-10 23:11:25作者: NJUPT

用来修饰父类中的函数:

1、修饰父类中的普通函数:

 1 #include <iostream>
 2 #include <string>
 3 #include <stdlib.h>
 4 
 5 using namespace std;
 6 
 7 class base
 8 {
 9 public:
10     void fun1(){ cout << "this is base::fun1" << endl;}
11     virtual void fun2(){ cout << "this is base::fun2" << endl;}
12 };
13 
14 class base1:public base
15 {
16 public:
17     void fun1(){ cout << "this is base1::fun1" << endl;}
18     void fun2(){ cout << "this is base1::fun2" << endl;}
19 };
20 
21 int main(int argc, char *argv[])
22 {
23     if (argc);
24     if (argv);
25 
26     base *p = new base1();
27 
28     p->fun1();
29     p->fun2();
30 
31     return 0;
32 }

输出:

this is base::fun1
this is base1::fun2

使用virtual修饰的函数会根据实际对象的类型来调用,没有使用virtual修饰的根据指针的类型来调用。关键的特点是“动态联编”,可以在运行时判断指针的指向的对象,并自动调用相关的函数。

2、修饰父类中的析构函数:

 1 #include <iostream>
 2 #include <string>
 3 #include <stdlib.h>
 4 
 5 using namespace std;
 6 
 7 class grandfather
 8 {
 9 public:
10     grandfather (){ cout << "this is grandfather::construct" << endl;}
11     ~grandfather(){ cout << "this is grandfather::destruct" << endl;}
12 };
13 
14 class father: public grandfather
15 {
16 public:
17     father (){ cout << "this is father::construct" << endl;}
18     ~father(){ cout << "this is father::destruct" << endl;}
19 };
20 
21 class son: public father
22 {
23 public:
24     son (){ cout << "this is son::construct" << endl;}
25     ~son(){ cout << "this is son::destruct" << endl;}
26 };
27 
28 int main(int argc, char *argv[])
29 {
30     if (argc);
31     if (argv);
32 
33     father *p = new son();
34 
35     delete p;
36 
37     return 0;
38 }

output:

this is grandfather::construct
this is father::construct
this is son::construct
this is father::destruct
this is grandfather::destruct

由此我们发现,这样操作没有析构掉son的内容,存在危险,

当father或者grandfather中的任一析构函数加上关键字virtual,

输出变为:

1 this is grandfather::construct
2 this is father::construct
3 this is son::construct
4 this is son::destruct
5 this is father::destruct
6 this is grandfather::destruct

符合预期

3、纯虚函数

在虚函数的后面加了一个=0;定义了纯虚函数的类是一个抽象类。

virtual void func() = 0;

注意:

  • 定义了纯虚函数的类不能实例化,即不能创建对象;
  • 继承了含有虚函数的父类的子类没有实现纯虚函数也不能够实例化;

 4、修饰继承性

若一个类继承的两个类或者多个类有公共的基类时:

 

 1 #include <iostream>
 2 #include <string>
 3 #include <stdlib.h>
 4 
 5 using namespace std;
 6 
 7 class grandfather
 8 {
 9 public:
10     grandfather (){ cout << "this is grandfather::construct" << endl;}
11     ~grandfather(){ cout << "this is grandfather::destruct" << endl;}
12 };
13 class father1: public grandfather
14 {
15 public:
16     father1 (){ cout << "this is father1::construct" << endl;}
17     virtual ~father1(){ cout << "this is father1::destruct" << endl;}
18 };
19 class father2: public grandfather
20 {
21 public:
22     father2 (){ cout << "this is father2::construct" << endl;}
23     virtual ~father2(){ cout << "this is father2::destruct" << endl;}
24 };
25 class son: public father1, father2
26 {
27 public:
28     son (){ cout << "this is son::construct" << endl;}
29     ~son(){ cout << "this is son::destruct" << endl;}
30 };
31 
32 int main(int argc, char *argv[])
33 {
34     if (argc);
35     if (argv);
36     father1 *p = new son();
37     delete p;
38     return 0;
39 }

 输出:

this is grandfather::construct
this is father1::construct
this is grandfather::construct
this is father2::construct
this is son::construct
this is son::destruct
this is father2::destruct
this is grandfather::destruct
this is father1::destruct
this is grandfather::destruct

出现了两次的grandfather的构造和析构,不符合预期;

所以在father1/2继承grandfather时需要加上virtual关键字

class father1: virtual public grandfather
{
public:
    father1 (){ cout << "this is father1::construct" << endl;}
    virtual ~father1(){ cout << "this is father1::destruct" << endl;}
};
class father2: virtual public grandfather
{
public:
    father2 (){ cout << "this is father2::construct" << endl;}
    virtual ~father2(){ cout << "this is father2::destruct" << endl;}
};

输出变为:

this is grandfather::construct
this is father1::construct
this is father2::construct
this is son::construct
this is son::destruct
this is father2::destruct
this is father1::destruct
this is grandfather::destruct

比较符合我们的预期