对象模型 - this

对象模型 - 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()调用方式一致
}

注意注释的讲解

posted @ 2024-04-15 18:04  俊king  阅读(1)  评论(0编辑  收藏  举报