本文介绍了多态性和虚函数的概念,以及它们在继承中的使用。
我们将介绍以下内容
- 定义
- 没有虚拟功能
- 使用虚拟函数
定义:
- A. 事实上的 函数是一个 成员 函数中声明的 基础 使用关键字virtual初始化,并由 衍生 班
- 术语 多态性 意味着能够采取多种形式。如果存在一个类的层次结构,这些类都通过 遗产 .

类层次结构
笔记 在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将所有方法都保持为虚拟 . 编译器如何执行运行时解析? 编译器维护两件事来达到这个目的:
编译器在两个地方添加额外的代码来维护和使用 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
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论