标签:
前言
当类没有成员变量的情况下, 类首地址有4个字节的空间, 这里可以放我们模拟出来的虚表入口地址.
当类有成员变量的情况下, 类首地址就是成员变量, 所以, 为了模拟虚表实现, 需要在成员变量前, 再定义一个int型变量, 用来存放模拟的虚表入口地址.
现在还得不到虚析构函数的地址, 暂时按照非虚析构函数进行模拟.
这个实验是在C++中模拟的.
模拟虚函数实现的用途
在非OOP语言(C语言)中, 模拟类的实现, 可以实现虚函数的效果.
效果
工程下载点
编译环境: vc6sp6 + win7x64
实现概览
-
-
- #include <iostream>
- #include <limits>
- #include "Person.h"
- #include "student.h"
-
- using namespace std;
-
- void clear_cin();
- void fnTestPolymorphismSimulation();
-
- int main(int argc, char** argv, char** envp)
- {
- fnTestPolymorphismSimulation();
-
- cout << "END, press any key to quit" << endl;
- clear_cin();
- getchar();
-
- return 0;
- }
-
- void fnTestPolymorphismSimulation()
- {
- Person per;
- student stu;
- Person* pAry[2] = {new Person(), new student()};
- size_t nIndex = 0;
-
- for (nIndex = 0; nIndex < (sizeof(pAry) / sizeof(pAry[0])); nIndex++)
- {
- pAry[nIndex]->SetId(3 + nIndex);
- }
-
- per.SetId(1);
- per.vsayHello();
- per.vsayGoodbye();
-
- stu.SetId(2);
- stu.vsayHello();
- stu.vsayGoodbye();
-
- for (nIndex = 0; nIndex < (sizeof(pAry) / sizeof(pAry[0])); nIndex++)
- {
- pAry[nIndex]->vsayHello();
- pAry[nIndex]->vsayGoodbye();
-
- delete pAry[nIndex];
- pAry[nIndex] = NULL;
- }
- }
-
- void clear_cin()
- {
- cin.clear();
- cin.sync();
- }
-
- #if !defined(AFX_PERSON_H__41F1DC26_8E95_4D75_811A_4B84F81E069E__INCLUDED_)
- #define AFX_PERSON_H__41F1DC26_8E95_4D75_811A_4B84F81E069E__INCLUDED_
-
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
-
- class Person
- {
- public:
- enum
- {
- e_MemberFnAry_index_destructor = 0,
- e_MemberFnAry_index_sayHello,
- e_MemberFnAry_index_sayGoodbye,
- e_MemberFnAry_index_Last_NULL,
- e_MemberFnAry_size
- };
- typedef void (Person::*PFN_memberFn)();
-
- public:
- Person();
- ~Person();
-
- void sayHello();
- void sayGoodbye();
-
- void vsayHello();
- void vsayGoodbye();
-
- void SetId(int nId) {m_nId = nId;}
- size_t GetId() {return m_nId;}
-
- private:
- void OverloadVirtualTable();
- void SetMemberFn(size_t nIndex, PFN_memberFn pFn);
- PFN_memberFn* getVirtualTable_by_member();
- PFN_memberFn* getVirtualTable_by_this();
-
-
-
-
- static PFN_memberFn m_pfnMemberFnAry[e_MemberFnAry_size];
-
-
- size_t m_nAddrVirtualTableEntry;
- size_t m_nId;
- };
-
- #endif // !defined(AFX_PERSON_H__41F1DC26_8E95_4D75_811A_4B84F81E069E__INCLUDED_)
-
- #if !defined(AFX_STUDENT_H__1A031AB4_8639_4C38_9A9A_6DE4095CD7CA__INCLUDED_)
- #define AFX_STUDENT_H__1A031AB4_8639_4C38_9A9A_6DE4095CD7CA__INCLUDED_
-
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
-
- #include "Person.h"
-
- class student : public Person
- {
- public:
- enum
- {
- e_MemberFnAry_index_destructor = 0,
- e_MemberFnAry_index_sayHello,
- e_MemberFnAry_index_sayGoodbye,
- e_MemberFnAry_index_Last_NULL,
- e_MemberFnAry_size
- };
- typedef void (student::*PFN_memberFn)();
-
- public:
- student();
- ~student();
-
- void sayHello();
- void sayGoodbye();
-
- void vsayHello();
- void vsayGoodbye();
-
- private:
- void OverloadVirtualTable();
- void SetMemberFn(size_t nIndex, PFN_memberFn pFn);
- PFN_memberFn* getVirtualTable_by_member();
- PFN_memberFn* getVirtualTable_by_this();
-
-
-
-
- static PFN_memberFn m_pfnMemberFnAry[e_MemberFnAry_size];
- };
-
- #endif // !defined(AFX_STUDENT_H__1A031AB4_8639_4C38_9A9A_6DE4095CD7CA__INCLUDED_)
-
- #include <iostream>
- #include "Person.h"
-
- using namespace std;
-
-
- Person::PFN_memberFn Person::m_pfnMemberFnAry[e_MemberFnAry_size];
- Person::Person()
- :m_nId(-1)
- {
- OverloadVirtualTable();
- }
-
- Person::~Person()
- {
- OverloadVirtualTable();
- }
-
- void Person::OverloadVirtualTable()
- {
-
- SetMemberFn(e_MemberFnAry_index_sayHello, &Person::sayHello);
- SetMemberFn(e_MemberFnAry_index_sayGoodbye, &Person::sayGoodbye);
- SetMemberFn(e_MemberFnAry_index_Last_NULL, NULL);
-
-
- (*(int*)this) = (int)getVirtualTable_by_member();
- }
-
- Person::PFN_memberFn* Person::getVirtualTable_by_member()
- {
- return m_pfnMemberFnAry;
- }
-
- Person::PFN_memberFn* Person::getVirtualTable_by_this()
- {
- return (Person::PFN_memberFn*)(*(int*)this);
- }
-
- void Person::SetMemberFn(size_t nIndex, PFN_memberFn pFn)
- {
- size_t nSizeAry = sizeof(m_pfnMemberFnAry) / sizeof(m_pfnMemberFnAry[0]);
-
- if (nIndex < nSizeAry)
- {
- m_pfnMemberFnAry[nIndex] = pFn;
- }
- }
-
- void Person::sayHello()
- {
- cout << "void Person::sayHello()" << " m_nId(" << GetId() << ")" << endl;
- }
-
- void Person::sayGoodbye()
- {
- cout << "void Person::sayGoodbye()" << " m_nId(" << GetId() << ")" << endl;
- }
-
- void Person::vsayHello()
- {
- PFN_memberFn* pFnAry = getVirtualTable_by_this();
-
- if (NULL != pFnAry)
- {
- (this->*(pFnAry[e_MemberFnAry_index_sayHello]))();
- }
- }
-
- void Person::vsayGoodbye()
- {
- PFN_memberFn* pFnAry = getVirtualTable_by_this();
-
- if (NULL != pFnAry)
- {
- (this->*(pFnAry[e_MemberFnAry_index_sayGoodbye]))();
- }
- }
-
- #include <iostream>
- #include "student.h"
-
- using namespace std;
-
-
- student::PFN_memberFn student::m_pfnMemberFnAry[e_MemberFnAry_size];
- student::student()
- {
- OverloadVirtualTable();
- }
-
- student::~student()
- {
- OverloadVirtualTable();
- }
-
- void student::OverloadVirtualTable()
- {
-
- SetMemberFn(e_MemberFnAry_index_sayHello, (PFN_memberFn)&student::sayHello);
- SetMemberFn(e_MemberFnAry_index_sayGoodbye, (PFN_memberFn)&student::sayGoodbye);
- SetMemberFn(e_MemberFnAry_index_Last_NULL, NULL);
-
-
- (*(int*)this) = (int)getVirtualTable_by_member();
- }
-
- void student::SetMemberFn(size_t nIndex, PFN_memberFn pFn)
- {
- size_t nSizeAry = sizeof(m_pfnMemberFnAry) / sizeof(m_pfnMemberFnAry[0]);
-
- if (nIndex < nSizeAry)
- {
- m_pfnMemberFnAry[nIndex] = pFn;
- }
- }
-
- void student::sayHello()
- {
- cout << "void student::sayHello()" << " m_nId(" << GetId() << ")" << endl;
- }
-
- void student::sayGoodbye()
- {
- cout << "void student::sayGoodbye()" << " m_nId(" << GetId() << ")" << endl;
- }
-
- void student::vsayHello()
- {
- PFN_memberFn* pFnAry = getVirtualTable_by_this();
-
- if (NULL != pFnAry)
- {
- (this->*(pFnAry[e_MemberFnAry_index_sayHello]))();
- }
- }
-
- void student::vsayGoodbye()
- {
- PFN_memberFn* pFnAry = getVirtualTable_by_this();
-
- if (NULL != pFnAry)
- {
- (this->*(pFnAry[e_MemberFnAry_index_sayGoodbye]))();
- }
- }
-
- student::PFN_memberFn* student::getVirtualTable_by_member()
- {
- return m_pfnMemberFnAry;
- }
-
- student::PFN_memberFn* student::getVirtualTable_by_this()
- {
- return (student::PFN_memberFn*)(*(int*)this);
- }
http://blog.csdn.net/lostspeed/article/details/50379125
http://download.csdn.net/detail/lostspeed/9371924
在类有成员变量的场景下, 按照虚表原理, 模拟虚函数实现
标签:
原文地址:http://www.cnblogs.com/findumars/p/5174318.html