余睿的博客

浮生若梦,别多会少,不如莫遇

0%

c++虚函数和多态的基本概念

虚函数

  • 在类的定义中,前面由virtual关键字的成员函数称为虚函数
  • virtual关键字只用在类定义里的函数声明中,写函数体时不用。
  • 构造函数和静态成员函数不能是虚函数。

多态的表现形式一

概念

  • 派生类的指针可以赋给基类指针
  • 通过基类指针调用基类和派生类中的同名虚函数时:
    • 若该指针指向一个基类对象,那么调用的为基类的虚函数。
    • 若该指针指向一个派生类,那么调用的为派生类的虚函数。

这种机制就叫做多态

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base {
public:
virtual void virtualFunction(){
cout << "Base类虚函数" << endl;
}
};
class Derived :public Base {
public:
virtual void virtualFunction() {
cout << "Derived类虚函数" << endl;
}
};

int main() {
Derived d;
Base b;
Base* p = &d;
p->virtualFunction();
p = &b;
p->virtualFunction();
return 0;
}

上面的实例中,Base类派生出Derived类,两个类中都有虚函数virtualFunction()

main函数中,我们初始化一个Derived对象d以及一个Base对象b

然后初始化一个Base类指针p,让p指向Derived对象d,然后调用virtualFunction()函数。

接着让p指向Base对象b,然后调用virtualFunction()函数。

执行上面程序,得到如下结果:

1
2
Derived类虚函数
Base类虚函数

我们可以知道,当p执行Derived类对象时,执行的是Derived类对象的virtualFunction()函数。

p指向Base类对象时,执行的为Base类对象的virtualFunction()函数。

多态的表现形式二

概念

  • 派生类对象可以赋值给基类的引用

  • 通过基类的引用调用基类和派生类中同名的虚函数时:

    • 若该引用引用的是一个基类对象,那么被调用的是基类的虚函数
    • 若该引用引用的是一个派生类对象,那么被调用的是派生类的虚函数。

    这种机制也叫做多态

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base {
public:
virtual void virtualFunction(){
cout << "Base类虚函数" << endl;
}
};
class Derived :public Base {
public:
virtual void virtualFunction() {
cout << "Derived类虚函数" << endl;
}
};

int main() {
Derived d;
Base b;
Base& r1 = b;
Base& r2 = d;
r1.virtualFunction();
r2.virtualFunction();
return 0;
}

在上面的实例中,Base类派生出Derived类,两个类中都有虚函数virtualFunction()

main函数中,我们初始化一个Derived对象d以及一个Base对象b

然后分别定义两个Base类的引用r1、r2,分别指向b、d

然后通过两个引用调用virtualFunction()函数。

得到如下的结果:

1
2
Base类虚函数
Derived类虚函数

可以证实:

  • 若该引用引用的是一个基类对象,那么被调用的是基类的虚函数
  • 若该引用引用的是一个派生类对象,那么被调用的是派生类的虚函数。

综合实例

定义如下的多重派生类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class A {
public:
virtual void print() {
cout << "A::print" << endl;
}
};
class B :public A {
public:
virtual void print() {
cout << "B::print" << endl;
}
};
class C :public A {
public:
virtual void print() {
cout << "C::print" << endl;
}
};
class D :public B {
public:
virtual void print() {
cout << "D::print" << endl;
}
};

他们之间的派生关系如下:

多重派生

假设由如下的调用实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {
A a;
B b;
C c;
D d;
A* p = &a;

p->print();
p = &b;
p->print();
p = &c;
p->print();
p = &d;
p->print();

return 0;
}

运行上面程序,得到如下结果:

1
2
3
4
A::print
B::print
C::print
D::print

多态的作用

在面向对象的程序设计中使用多态,能够增强程序的可扩充性,即程序需要修改或增加功能的时候,需要改动和增加的代码较少。

欢迎关注我的其它发布渠道