C++ virtual虚函数的用法(附带实例)
在类的继承层次结构中,不同层次中可以出现名字、参数个数和类型都相同但功能不同的函数,此时编译器会按照先自身、后基类的顺序进行查找覆盖。
当派生类中有与基类相同原型的成员函数时,调用基类成员函数需对基类重新引用调用。
虚函数可以解决派生类和基类中有相同原型成员函数时的函数调用问题。虚函数允许在派生类中重新定义与基类同名的函数,且允许通过基类指针或引用访问基类和派生类中的同名函数。具体做法是:在基类中用 virtual 声明成员函数为虚函数,在派生类中重新定义此函数,改变函数的功能。
C++ 中,虚函数可以继承。当一个成员函数被声明为虚函数后,其派生类中的同名函数将自动成为虚函数;如果派生类中没有覆盖基类的虚函数,则调用时调用基类的函数。
注意,重载和覆盖的区别是:
虚函数有以下几方面限制:
【实例】输出操作员姓名。本实例要求利用虚函数实现动态绑定,具体代码如下:
当派生类中有与基类相同原型的成员函数时,调用基类成员函数需对基类重新引用调用。
虚函数可以解决派生类和基类中有相同原型成员函数时的函数调用问题。虚函数允许在派生类中重新定义与基类同名的函数,且允许通过基类指针或引用访问基类和派生类中的同名函数。具体做法是:在基类中用 virtual 声明成员函数为虚函数,在派生类中重新定义此函数,改变函数的功能。
C++ 中,虚函数可以继承。当一个成员函数被声明为虚函数后,其派生类中的同名函数将自动成为虚函数;如果派生类中没有覆盖基类的虚函数,则调用时调用基类的函数。
注意,重载和覆盖的区别是:
- 重载是同一层次内多个函数名相同;
- 覆盖是继承层次中多个成员函数的函数原型完全相同。
C++虚函数实现动态绑定
多态主要体现在虚函数上,只要有虚函数存在,对象类型就在程序运行时动态绑定。动态绑定的实现方法是定义一个指向基类对象的指针变量,并使它指向同一类中需要调用该函数的对象,通过该指针变量调用此虚函数。虚函数有以下几方面限制:
- 只有类的成员函数才能成为虚函数;
- 静态成员函数不能是虚函数,因为静态成员函数不受限于某个对象;
- 内联函数不能是虚函数,因为内联函数不能在运行中动态确定其位置;
- 构造函数不能是虚函数,析构函数通常是虚函数。
【实例】输出操作员姓名。本实例要求利用虚函数实现动态绑定,具体代码如下:
#include <iostream> #include <cstring> using namespace std; class CEmployee // 定义 CEmployee 类 { public: int m_ID; char m_Name[128]; char m_Depart[128]; CEmployee() // 基类构造函数 { memset(m_Name, 0, 128); memset(m_Depart, 0, 128); } virtual void OutputName() // 基类虚函数 OutputName() { cout << "员工姓名:" << m_Name << endl; } }; class COperator : public CEmployee // 定义 COperator 类,继承自 CEmployee { public: char m_Password[128]; void OutputName() override // 派生类虚函数 OutputName() { cout << "操作员姓名:" << m_Name << endl; } }; int main(int argc, char *argv[]) { CEmployee *pWorker = new COperator(); // 定义 CEmployee 指针,指向 COperator 对象 strcpy(pWorker->m_Name, "MR"); // 设置 m_Name 成员变量 pWorker->OutputName(); // 调用 COperator 类的 OutputName() 函数 delete pWorker; // 释放对象 return 0; }运行结果为:
操作员姓名:MR
注意,重写虚函数时,函数原型必须保持一致。例如,基类为 int 类型,子类重写时也必须为 int 类型。