C++如何理解和使用虚函数和运行时多态？(用法示例+图解)|S1

2021年3月27日15:26:11 发表评论 645 次浏览

本文概述

• 定义
• 没有虚函数
• 使用虚函数

定义：

1. 虚函数是在基类中使用关键字virtual声明并由派生类重新定义(重写)的成员函数。
2. 术语多态性意味着采取多种形式的能力。如果存在通过继承相互关联的类的层次结构，则会发生这种情况。

C++

``````#include <iostream>
using namespace std;

// Base class
class Shape
{
public :
Shape( int l, int w)
{
length = l;
width = w;
} // default constructor
int get_Area()
{
cout << "This is call to parent class area" << endl;
}

protected :
int length, width;
};

// Derived class
class Square : public Shape
{
public :
Square( int l = 0, int w = 0)
: Shape(l, w)
{
} // declaring and initializing derived class
// constructor
int get_Area()
{
cout << "Square area: " << length * width << endl;
return (length * width);
}
};
// Derived class
class Rectangle : public Shape
{
public :
Rectangle( int l = 0, int w = 0)
: Shape(l, w)
{
} // declaring and initializing derived class
// constructor
int get_Area()
{
cout << "Rectangle area: " << length * width
<< endl;
return (length * width);
}
};

int main( void )
{
Shape* s;
Square sq(5, 5); // making object of child class Sqaure
Rectangle rec(
4, 5); // making object of child class Rectangle

s = &sq;
s->get_Area();
s = &rec;
s->get_Area();

return 0;
}``````

``````This is call to parent class area
This is call to parent class area``````

• 我们存储每个子类的地址长方形和广场对象在s和
• 然后我们称get_Area()函数,
• 理想情况下, 它应该已经get_Area()子类的函数, 但
• 相反, 它称为get_Area()在基类中定义。
• 发生这种情况是由于静态链接, 这意味着调用get_Area()由基类中的编译器仅设置一次。

CPP

``````class Employee {
public :
virtual void raiseSalary()
{
/* common raise salary code */
}

virtual void promote() { /* common promote code */ }
};

class Manager : public Employee {
virtual void raiseSalary()
{
/* Manager specific raise salary code, may contain
increment of manager specific incentives*/
}

virtual void promote()
{
/* Manager specific promote */
}
};

// Similarly, there may be other types of employees

// We need a very simple function
// to increment the salary of all employees
// Note that emp[] is an array of pointers
// and actual pointed objects can
// be any type of employees.
// This function should ideally
// be in a class like Organization, // we have made it global to keep things simple
void globalRaiseSalary(Employee* emp[], int n)
{
for ( int i = 0; i < n; i++)

// Polymorphic Call: Calls raiseSalary()
// according to the actual object, not
// according to the type of pointer
emp[i]->raiseSalary();
}``````

1. vtable：每个类维护的函数指针表。
2. vptr：指向vtable的指针, 针对每个对象实例进行维护(请参见这个例如)。

1)每个构造函数中的代码。这段代码设置要创建的对象的vptr。这段代码将vptr设置为指向类的虚函数表。

2)带有多态函数调用的代码(如上面代码中的bp->show())。无论在哪里进行多态调用，编译器都会先插入代码，使用基类指针或引用来查找vptr(在上面的例子中，因为指向或引用的对象是派生类型的，所以要访问派生类的vptr)。一旦获取了vptr，就可以访问派生类的虚函数表。使用vtable访问和调用派生类函数show()的地址。

C++标准没有明确规定必须如何实现运行时多态性, 但是编译器通常在同一基本模型上使用较小的变体。

http://en.wikipedia.org/wiki/Virtual_method_table

http://en.wikipedia.org/wiki/Virtual_function

http://www.drbio.cornell.edu/pl47/programming/TICPP-2nd-ed-Vol-one-html/Frames.html