C++进阶剖析(二十一)之对象模型分析

1.1对象模型分析
1.1.1 对象模型分析的本质

  • C++中的对象分为两个部分:对象的成员变量和对象的成员函数,对象模型分析就是对对象的成员变量和成员函数进行分析。
    1.1.2类对象的本质
    class 是一种特殊的struct
  • 在内存中class依旧可以看做变量的集合
  • class 与struct 遵循相同的内存对齐规则
  • class中的成员变量和成员函数是分开存放的
    (1)每个对象都有独立的成员变量(在堆,栈,全局数据区分配内存)
    (2)成员函数本质是函数,只能在代码区分配内存,所有类对象共享类中的成员函数。

1.1.3实例代码

#include <iostream>
using namespace std;
class Test
{
	char a;
	int b;
	int c;
	double d;
public:
	void print()
	{
		cout <<" a= "<<a <<"  b= "<< b<<"  c = "<<c <<" d= "<<d<<endl;
	}
};

struct ST
{
	char a;
	int b;
	int c;
	double d;
};
int main()
{	
	Test t1;
	ST *st;
	st =reinterpret_cast<ST*>(&t1);
	
	st->a ='A';
	st->b=10;
	st->c=20;
	st->d=3.14;
	t1.print();	
	return 0;
}

运行结果:
在这里插入图片描述
1.1.4运行时对象退化成结构体的形式

  • 所有成员变量在内存中依次排布
  • 成员变量间可能存在内存空隙
  • 可以通过内存地址直接访问成员变量
  • 访问权限关键字在运行时失效

总结

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

1.1.5代码实例
下面是 .cpp文件

#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 << "d.getI() = " << d.getI() << endl;
    cout << "d.getJ() = " << d.getJ() << endl;
    cout << "d.add(3) = " << d.add(3) << endl;
    
    return 0;
}
  • 使用C语言完成面向对象的程序

  • 下面是.c 文件

#include <stdio.h>
#include <stdlib.h>
#include "Test.h"

struct Test
{
	int i ;
	int j;
};

Demo* Demo_create(int i,int j)
{
	struct Test * t = (struct Test *)malloc(sizeof(struct Test));
	if(t != NULL)
	{
		t->i =i;
		t->j =j;
	}
	return t;

}
int   GetI(Demo* demo)
{
	struct Test * t =(struct Test * )demo;
	return t->i;
}
int   GetJ(Demo * demo)
{
		struct Test * t =(struct Test*) demo;
		return t->j;
}
int   SetI(Demo *demo ,int i)
{
	struct Test * t =(struct Test*) demo;
	t->i =i;

}
int   SetJ(Demo * demo,int j)
{
	struct Test * t =(struct Test*) demo;
	t->j =j;
}
void  Demo_free(Demo* demo)
{
	free(demo);
}

下面是.h文件

#ifndef __TEST_H
#define __TEST_H 

typedef void Demo;  //和C++中private的作用相同

Demo* Demo_create(int i,int j);
int   GetI(Demo* demo);
int   GetJ(Demo * demo);
int   SetI(Demo *demo ,int i);
int   SetJ(Demo * demo,int j);
void  Demo_free(Demo* demo);

#endif

下面是 main.c

#include <stdio.h>
#include <stdlib.h>
#include "Test.h"
int main()
{	
	Demo *d = Demo_create(10,20);

	printf("i =%d\n",GetI(d));
	printf("j= %d\n",GetJ(d));
	Demo_free(d);

	return 0;
}

遇到问题有,在编写的过程中将main文件定义成了main.cpp导致程序找不到函数入口

1.2继承中对象模型初探
1.2.1 继承中对象模型

  • 继承中子类是由父类成员叠加子类新成员得到的

1.2.2 继承模型初探示例

  • 代码示例
class Demo
{
protected:
	int mi;
	int mj;
};
class Derived : public Demo
{
protected:
	int mk;
public:
	Derived(int i ,int j ,int k)
	{
		mi = i;
		mj = j;
		mk = k;
	}
	void print()
	{
		cout<< "mi = " <<mi <<endl;
		cout<< "mj = " <<mj <<endl;
		cout<< "mj = " <<mk <<endl;
	}
};

struct Test
{
	int mi;
	int mj;
	int mk;
};

int main()
{  
	cout<<"sizeof(Demo) "<<sizeof(Demo)<<endl;         // 8  //如果函数是virtual的就是 12
	cout<<"sizeof(Derived) "<<sizeof(Derived)<<endl;	//12 //如果函数是virtual的就是 16
	Derived d(1,2,3);
	Test *p = reinterpret_cast<Test*>(&d);
	d.print();
	cout<<endl;
	cout<<"after change "<<endl;
	p->mi =10;
	p->mj= 20;
	p->mk =30;
	d.print();

	return 0;
}

在这里插入图片描述

  • 实验说明 : 继承以后成员的分布是父类的成员在前面,子类的成员在后面
  • 实验说明二: 存在虚函数的时候,会在结构体中自动加入一个指向虚函数表的指针

1.3 C++中多态的实现
1.3.1多态原理

  • 当声明虚函数的时候,编译器会在类中生成一个虚函数表
  • 虚函数表是一个存储成员函数的数据结构
  • 虚函数表是由编译器自动生成和维护的
  • virtual成员函数会被编译器放入虚函数表中
  • 存在虚函数时,每个对象中都与一个指向虚函数变的指针

1.3.2 多态VS虚函数

  • 多态:是面向对象程序设计中的一个概念,相同的行为方式,不同的行为结果
  • 虚函数: C++中通过虚函数进行实现的。
    1.3.3 模型图解在这里插入图片描述
  • 上图中 子类的虚函数表中应该是 int Child::add(int value);
  • 每一个对象都对应属于自己的虚函数表
    在这里插入图片描述
  • 调用效率对比: 虚函数 < 普通成员函数

1.3.3 多态本质
.h文件

#ifndef __TEST_H
#define __TEST_H 

typedef void Parent;
typedef void Child;

Parent * parent_create(int i ,int j);
int  getI(Parent * parent);
int  getJ(Parent* parent);
int parent_add(Parent* parent ,int value);
void parent_free(Parent* parent);


Child * child_creat(int i,int j ,int k);
int getK(Child * child);
int child_add(Child* child,int value);
#endif

.c文件

#include <stdio.h>
#include <stdlib.h>
#include "Test.h"

static int parent_virtual_add(Parent* parent ,int value);
static int child_virtual_add(Child* child,int value);
struct classParent
{
	struct vtable * vptr;
	int i;
	int j;
};
struct classChild
{

	struct classParent p;
	int k;
};


struct vtable
{
	int  (*pAdd)(Parent* ,int);
};

struct vtable parent_virtual_table=
{
	parent_virtual_add
};
struct vtable child_virtual_table=
{
	child_virtual_add
};


Parent * parent_create(int i ,int j)
{
	struct classParent * p = (struct classParent*)malloc(sizeof(struct classParent));
	if(p != NULL)
	{
		p->vptr = &parent_virtual_table;
		p->i=i;
		p->j=j;
	}
	return p;
}
int  getI(Parent * parent)
{
	struct classParent * p = (struct classParent*)parent;
	return p->i;

}
int  getJ(Parent* parent)
{
	struct classParent * p = (struct classParent*)parent;
	return p->j;
}
static int parent_virtual_add(Parent* parent ,int value)
{
	struct classParent * p = (struct classParent*)parent;
	return p->i + p->j + value;
}

int parent_add(Parent* parent ,int value)
{

	struct classParent * p = (struct classParent*)parent;
	return p->vptr->pAdd(p,value);
}
void parent_free(Parent* parent)
{
	free(parent);
}

Child * child_creat(int i,int j ,int k)
{
	struct classChild * ret = (struct classChild *) malloc(sizeof(struct classChild));
	 if(ret != NULL)
	 {
		 ret->p.vptr= &child_virtual_table;
		 ret->p.i =i;
		 ret->p.j =j;
		 ret->k =k;
	 }
	 return ret;
	
}
int getK(Child * child)
{
	struct classChild * ret =(struct classChild *)child;
	
	return ret->k;

}
int child_virtual_add(Child* child,int value)
{
	struct classChild * ret =(struct classChild *)child;
	return ret->k + value;
}
int child_add(Child* child,int value)
{
	struct classChild * ret =(struct classChild *)child;
	
	return ret->p.vptr->pAdd(ret,value);
}


main.c文件

#include <stdio.h>
#include <stdlib.h>
#include "Test.h"
void howtoadd(Parent* p ,int v)
{
	int r =parent_add(p,v);
	printf("r = %d\n", r);
}
int main()
{	

	Parent * p = parent_create(1,2);
    
	//printf("%d\n",getI(p));
	Child * cp =child_creat(1,22,333);
	printf("%d\n",parent_add(p,3));
	printf("%d\n",child_add(cp,3));
	howtoadd(p,3);
	howtoadd(cp,3);

	parent_free(p);
	parent_free(cp);
	return 0;
}


参考一 :狄泰软件学院C++进阶剖析
参考二 : C++ primer中文版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值