C++ 1中的虚函数和运行时多态性(引言)

本文介绍了多态性和虚函数的概念,以及它们在继承中的使用。

我们将介绍以下内容

  • 定义
  • 没有虚拟功能
  • 使用虚拟函数

定义:

  1. A. 事实上的 函数是一个 成员 函数中声明的 基础 使用关键字virtual初始化,并由 衍生
  2. 术语 多态性 意味着能够采取多种形式。如果存在一个类的层次结构,这些类都通过 遗产 .
Polymorphism

null

类层次结构

笔记 在C++中,这意味着如果我们调用一个成员函数,那么它可以导致一个不同的函数被执行,而取决于对象调用了什么类型的对象。

以下面的简单程序为例 运行时多态性 .关于该程序,需要注意的主要问题是使用基类指针调用派生类的函数。 想法是 虚拟函数 根据指向或引用的对象实例的类型而不是指针或引用的类型调用。 换句话说,虚拟函数在运行时很晚才被解析。 现在,我们来看一个例子,使用这两个概念来阐明您的理解。

C++

#include <iostream>
using namespace std;
// Base class
class Shape
{
public :
Shape( int l, int w)
{
length = l;
width = w;
} // parameterized constructor
int get_Area()
{
cout << "This is call to parent class area" ;
return 1;
}
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 << '' ;
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 << '' ;
return (length * width);
}
};
int main()
{
Shape* s;
// Making object of child class Square
Square sq(5, 5);
// Making object of child class Rectangle
Rectangle rec(4, 5);
s = &sq;
s->get_Area();
s = &rec;
s->get_Area();
return 0;
}


输出

This is call to parent class areaThis is call to parent class area

在上述功能中:

  • 我们存储每个子类的地址 长方形 广场 反对 s
  • 然后我们打电话给 获取_区域() 它的功能,
  • 理想情况下,它应该调用相应的 获取_区域() 子类的功能,但
  • 相反,它称之为 获取_区域() 在基类中定义。
  • 这是由于静态链接导致的,这意味着调用 获取_区域() 仅由基类中的编译器设置一次。

有什么用? 虚拟函数允许我们创建基类指针列表,并调用任何派生类的方法,甚至不知道派生类对象的类型。

实例

考虑一个组织的雇员管理软件。 让代码有一个简单的基类 受雇者 ,该类包含虚拟函数,如 赖斯拉里 , 转移() , 促进 不同类型的员工 经理 , 工程师 等,可能会在基类中有自己的虚拟函数实现 受雇者 . 在我们完整的软件中,我们只需要在不知道员工类型的情况下到处传递员工列表,并调用适当的函数。例如,我们可以通过遍历员工列表轻松提高所有员工的工资。每种类型的员工可能在其类中都有自己的逻辑,但我们不需要担心它们,因为如果 赖斯拉里 对于特定的员工类型,只会调用该函数。

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();
}
}


喜欢 globalRaiseSalary() ,甚至不知道对象实例的类型,也可以对员工列表执行许多其他操作。 虚拟函数非常有用,以至于后来的语言 默认情况下,Java将所有方法都保持为虚拟 . 编译器如何执行运行时解析? 编译器维护两件事来达到这个目的:

  1. vtable: 函数指针表,按类维护。
  2. vptr: 指向vtable的指针,按对象实例维护(请参见 例如)。

compiler perform runtime resolution

编译器在两个地方添加额外的代码来维护和使用 vptr . 1) 在每个构造函数中编写代码。此代码设置 vptr 正在创建的对象的。此代码设置 vptr 函数表 全班同学。 2) 带有多态函数调用的代码(例如。 bp->show() 在上面的代码中)。无论在哪里进行多态调用,编译器都会插入代码以首先查找 vptr 使用基类指针或引用(在上面的示例中,由于指针或引用的对象是派生类型, vptr 已访问派生类的)。一旦 vptr 被带走了, 函数表 可以访问派生类的。使用 函数表 ,派生类函数的地址 show() 被访问和调用。

这是C++中实现运行时多态性的标准方法吗? 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

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享