对象模型 - this
通过一个对象来调用一个函数,那么对象的地址就是this
虚函数的模板方法使用方式
template method
示例代码:
#pragma
#ifndef __THIS_TEMPLATE_MODEL__
#define __THIS_TEMPLATE_MODEL__
class CDocument
{
public:
virtual void Serialize();
void OnFileOpen();
private:
};
inline void CDocument::OnFileOpen() {
Serialize();
}
class CMyDoc : public CDocument
{
public:
virtual void Serialize() {};
private:
};
#endif // !__THIS_TEMPLATE_MODEL__
调用代码:
#include <iostream>
#include "this_template_model.hpp"
using namespace std;
int main() {
CMyDoc myDoc;
myDoc.OnFileOpen();
/*
* 子类调用者被作为this传入父类方法当中
* CDocument::OnFileOpen(&myDoc);
* myDoc是CMyDoc的对象.继承于CDocument,符合向上转型的动作
* 由于this指向子类.所以调用到的是子类的虚函数而不是父类的虚函数
*/
return 0;
}
分析调用代码:
-
myDoc.OnFileOpen()
-> 会走到父类的函数空间 -
父类的函数空间当中执行了虚函数 -> 由于是虚函数,那么由子类去定义具体的实现方式 -> 会回到子类执行对应的方法 -> 通过动态绑定实现的
-
最后回到父类执行完方法
-
由于是调用父类的方法,所以子类被传入父类方法中.子类就是
this
-
c++
当中所有的成员函数都有一个隐藏的this
作为参数 -
传入之后所有的子类调用父类方法都被编译器视为
( *(this -> vptr[n] (this))
->this
是一根指针
现实生活当中有很多这样的情况.上层(父类)只能定义出大纲.具体执行由子类执行,大纲当中会包含要做什么但是不会具体写明要做什么(这就是类似虚函数的概念)
对象模型(Dynamic Binding)
示例代码:
#pragma
#ifndef __VPTR_AND_VTBL__
#define __VPTR_AND_VTBL__
class A
{
public:
virtual void vfunc1();
virtual void vfunc2();
void func1();
void func2();
private:
int m_data_one, m_data_two;
};
class B : public A
{
public:
virtual void vfunc1();
void func2();
private:
int m_data_three;
};
class C : public B
{
public:
virtual void vfunc1();
void func2();
private:
int m_data_one, m_data_four;
};
#endif // !__VPTR_AND_VTBL__
调用方式:
#include <iostream>
#include "vptr_and_vtbl.hpp"
int main() {
B b;
A a = (A)b;
a.vfunc1();
/*
* 这里a是A类,且A是基类
* 所以直接调用的是A的虚函数
* 所以在汇编层面会直接call -> vfunc1()的地址
*/
A* pa = new B;
pa->vfunc1();
/*
* 这里因为指针pa是指向B的
* B继承A类
* B重写了A类的虚函数
* 那么在汇编层面.不会直接call -> vfunc1()地址 -> 而是会去找到虚指针 -> call dword ptr [edx]
* c中表示是(* p->vptr[n])(p)
*/
pa = &b;
pa->vfunc1(); // 和上面的pa->vfunc1()调用方式一致
}
注意注释的讲解
标签:__,对象,子类,模型,public,vfunc1,父类,void From: https://www.cnblogs.com/JunkingBoy/p/18136641