浅谈C++虚函数

来源:互联网 发布:八一电视软件 编辑:程序博客网 时间:2024/05/22 05:02

以下皆是我个人见解,有不当之处敬请指出纠正,谢谢!


        多态是C++的一个重要的特性,而往往通过虚函数来实现多态这一特性。在介绍虚函数实现原理前,这里首先介绍一下C++编译时内存区的一些概念,主要分为静态数据区、静态代码区、堆内存区、栈内存区。静态内存区主要存放了一些静态变量、全局变量等;函数编译后的一些指令代码都存放在代码区;在堆内存区中,C++程序员可以自己开辟内存空间和释放内存空间;栈内存区主要存放一些普通的局部变量。那么虚函数实现多态的过程是怎么完成的呢?


这里举个简单的例子:

#include <iostream>#include <stdio.h>#define MAX_NAME_LEN 128//定义父类CPersonclass CPerson{public:CPerson(char* szName, int nAge);CPerson(){}~CPerson();void PrintAge();virtual void PrintName();virtual void SetName(char* szName = "jackie");char m_szName[MAX_NAME_LEN];int  m_nAge;};CPerson::CPerson(char* szName, int nAge){memcpy(m_szName, szName, strlen(szName) + 1);m_nAge = nAge;}CPerson::~CPerson(){}void CPerson::PrintAge(){std::cout<<"CPerson::"<<std::endl;std::cout<<"The person's age is "<<m_nAge<<std::endl;}void CPerson::PrintName(){std::cout<<"CPerson::"<<std::endl;std::cout<<"The person's name is "<<m_szName<<std::endl;}void CPerson::SetName(char* szName /* = */ ){std::cout<<"CPerson::"<<std::endl;memcpy(m_szName, szName, strlen(szName) + 1);}//定义 类CPerson的子类CStudentclass CStudent : public CPerson{public:CStudent(char* szName, int nAge);~CStudent();virtual void PrintName();virtual void SetName(char* szName = "maikel");};CStudent::CStudent(char* szName, int nAge){memcpy(m_szName, szName, strlen(szName) + 1);m_nAge = nAge;}CStudent::~CStudent(){}void CStudent::PrintName(){std::cout<<"CStudent::"<<std::endl;std::cout<<"The student's name is "<<m_szName<<std::endl;}void CStudent::SetName(char* szName /* = */ ){std::cout<<"CStudent::"<<std::endl;memcpy(m_szName, szName, strlen(szName) + 1);}int main(int argc, char** argv){CPerson* pPer = new CStudent("fang", 18);pPer->PrintAge();pPer->PrintName();pPer->SetName();pPer->PrintName();getchar();return 0;}

        上面代码中定义了两个类CPeron和CStudent,其中CPerson是CStudent的父类。对于类中一般的成员函数,当掉作用这个函数时是直接跳入所在函数的代码段的,是静态的。比如说,我们这里在CPerson中定义了一个普通的成员函数PrintAge(),当有一个指向CPerson类型的指针pPer时。在pPer调用PrintAge()时是直接跳进自己类型(也就是CPerson)所拥有的PrintAge()函数代码段的。这也称作静态绑定。对于一个存在虚函数的类,它比没有虚函数的类多了一个非常重要的指向虚函数表的指针。每个有虚函数的类中都有一个指向虚函数表的指针,而这个指针也就是实现多态的关键所在。所以当我们千万不要对一个类轻易memset,因为这可能破坏它的虚函数表的指针。

        再来看看这个例子,当定义一个CPerson类型的指针pPer,并且把pPer指向其子类CStudent的一个对象,当pPer调用虚函数PrintName和SetName时,首先会找到对应类中的虚函数表指针vptr,根据vptr找到对应的实现。


实现结果:



原创粉丝点击