第50 课C++对象模型分析——成员函数(上)

类中的成员函数位于代码段中
调用成员函数时对象地址作为参数隐式传递
成员函数通过对象地址访问成员变量
C++语法规则隐藏了对象地址的传递过程

#include<iostream>
#include <string>

using namespace std;

class Demo
{
    int mi;
    int mj;
public:
    Demo(int i, int j)
    {
       mi = i;
       mj = j;
    }
    int getI()
    {
        return mi;
    }
    int getJ()
    {
        return mj;
    }
    int add(int value)
    {
        return mi + mj + value;
    }
};

int main()
{
    Demo d(1,2);
    cout << "sizeof(d) =" << sizeof(d) <<endl;
    cout << "getI()=" << d.getI() << endl;
    cout << "getJ()=" << d.getJ() << endl;
    cout << "d.add(3)=" << d.add(3) << endl;

    return 0;
}

d.getI()
d对象的地址被传到了getI这个函数的内部,但是传递过程在C++代码中是看不到的。深度挖掘的就是编译器背后的故事,此时就需要用到C语言了,用C语言实现这个面向对象的程序。

50-2.h

#ifndef _50_2_H_
#define _50_2_H_

typedef void Demo;

Demo* Demo_Create(int i, int j);
int Demo_GetI(Demo* pThis);
int Demo_GetJ(Demo* pThis);
int Demo_Add(Demo* pThis, int value);
void Demo_Free(Demo* pThis);

#endif

50-2.c

#include "50-2.h"
#include "malloc.h"

struct ClassDemo
{
    int mi;
    int mj;
};

Demo* Demo_Create(int i, int j)
{
    struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo));

    if( ret != NULL )
    {
        ret->mi = i;
        ret->mj = j;
    }

    return ret;
}

int Demo_GetI(Demo* pThis)
{
     struct ClassDemo* obj = (struct ClassDemo*)pThis;

     return obj->mi;
}

int Demo_GetJ(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->mj;
}

int Demo_Add(Demo* pThis, int value)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->mi + obj->mj + value;
}

void Demo_Free(Demo* pThis)
{
    free(pThis);
}

main.c

#include <stdio.h>
#include "50-2.h"

int main()
{
    Demo* d = Demo_Create(1, 2);             // Demo* d = new Demo(1, 2);

    printf("d.mi = %d\n", Demo_GetI(d));     // d->getI();
    printf("d.mj = %d\n", Demo_GetJ(d));     // d->getJ();
    printf("Add(3) = %d\n", Demo_Add(d, 3));    // d->add(3);

    // d->mi = 100;

    Demo_Free(d);

    return 0;
}

面向对象不是C++专属的,依然可以用C语言写面向对象

原文地址:https://www.cnblogs.com/-glb/p/11965580.html

时间: 2024-11-09 12:27:13

第50 课C++对象模型分析——成员函数(上)的相关文章

第50课 C++对象模型分析(上)

1. 回归本质 (1)class是一种特殊的结构体 ①在内存中class依旧可以看作变量的集合 ②class与struct遵循相同的内存对齐规则 ③class中的成员函数与成员变量是分开存放的.即每个对象有独立的成员变量,但所有对象共享类中的成员函数. [编程实验]对象内存布局初探 #include <iostream> #include <string> using namespace std; class A { //默认访问权限为private int i; int j; c

第51课 C++对象模型分析(下)

1. 单继承对象模型 (1)单一继承 [编程实验]继承对象模型初探 #include <iostream> using namespace std; class Demo { protected: int mi; int mj; public: //虚函数 virtual void print() { cout << "mi = " << mi << ", " << "mj = " &l

第51课 继承对象模型分析——多态的本质分析

多态的本质分析 用C写面向对象,用C实现多态 #ifndef _51_2_H_ #define _51_2_H_ typedef void Demo; typedef void Derived; Demo* Demo_Create(int i, int j); int Demo_GetI(Demo* pThis); int Demo_GetJ(Demo* pThis); int Demo_Add(Demo* pThis, int value); void Demo_Free(Demo* pThi

第五十课、c++对象模型分析(上)

一.c++对象模型之成员变量 1.class是一种特殊的struct (1).在内存中class依旧可以看做是变量的集合 (2).class与struct遵循相同的内存对齐规则 (3).class中的成员函数和成员变量是分开存储的 A.每个对象有独立的成员变量 B.所有对象共享类中的成员函数 2.运行时的对象退化为结构体的形式 (1).所有成员变量在内存中依次分布 (2).成员变量间可能存在内存间隙 (3).可以通过内存地址直接访问成员变量 (4).访问权限关键字在运行时失效 #include<

【反汇编分析】C++成员函数和虚函数

本节通过反汇编研究C++非static成员函数和虚函数的执行流程: 代码片段如下 class Animal { public: virtual void print() { cout << "Animal::print "<< endl; } void print2() { cout << "Animal::print2 "<< endl; } }; class Dog : public Animal { public

C++ 类中成员函数分析

概述之前对成员变量的分布进行了整理,今天就对成员函数进行整理. 1.非静态成员函数C++的设计准则之一就是:非静态成员函数至少和一般的非成员函数的执行效率相同. 为了实现上衣准则,编译器会对非静态成员函数进行改进,先看下面的例子: float func(const Point3d* _this) { .... } float Point3d::func() const { .... }123编译器对会Point3d::func()做下面三个步骤的操作: 1.改写函数func以安插一个额外的参数到

第五十一课、c++对象模型分析(下)

一.继承的本质 1.在c++编译器的内部类可以理解为结构体 2.子类是由父类成员叠加子类新成员得到的 二.多态的本质 1.当类中声明一个虚函数时,编译器会在类中生成一个虚函数表 2.虚函数表是一个存储成员函数地址的数据结构 3.虚函数表是由编译器自动生成与维护的 4.virtual成员函数会被编译器放入虚函数表中 5.存虚函数时,每个对象都有一个指向虚函数表的指针 #include<iostream> using namespace std; class Demo { protected: i

C#中Stack&amp;lt;T&amp;gt;类的使用及部分成员函数的源代码分析

Stack<T>类 Stack<T> 作为数组来实现. Stack<T> 的容量是 Stack<T> 能够包括的元素数. 当向 Stack<T> 中加入元素时,将通过又一次分配内部数组来依据须要自己主动增大容量. 可通过调用 TrimExcess 来降低容量. 假设 Count 小于堆栈的容量,则 Push 的运算复杂度是 O(1). 假设须要添加容量以容纳新元素,则 Push 的运算复杂度成为 O(n).当中 n 为 Count. Pop 的运

C#中Stack&lt;T&gt;类的使用及部分成员函数的源码分析

Stack<T>类 Stack<T> 作为数组来实现. Stack<T> 的容量是 Stack<T> 可以包含的元素数. 当向 Stack<T> 中添加元素时,将通过重新分配内部数组来根据需要自动增大容量. 可通过调用 TrimExcess 来减少容量. 如果 Count 小于堆栈的容量,则 Push 的运算复杂度是 O(1). 如果需要增加容量以容纳新元素,则 Push 的运算复杂度成为 O(n),其中 n 为 Count. Pop 的运算复杂