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中文版