一、C++对象模型讨论
方案一:各对象完全独立地安排内存地方案(并没有实现代码,仅为理论)
上图是系统为每一个对象分配了全套的内存,包括安放成员数据的数据区和安放成员函数的代码区。但是区别同一个类所实例化的对象,是由属性(数据成员)的值决定,不同对象的数据成员的内容是不一样的;而行为(操作)是用函数来描述的,这些操作的代码对所有的对象都是一样的。
方案二:各对象的代码区共用的方案(内存分配方案)
上图仅为每个对象分配一个数据区,代码区(放成员函数的区域)为各对象类共用
总结:对象模型中的存储区分配
void CGood::RegisterGoods(const char *name,int amount,float price)
{
strcpy(Name,name); //字符串拷贝函数
Amount = amount;
Price = price;
}
int main()
{
CGoods tea;
CGoods book;
tea.RegisterGoods("black_tea",12,560);
tea.CountTotal();
book.RegisterGoods("Thinking In C++",20,128);
book.CountTotal();
return 0;
}
当执行:
tea.RegisterGoods("black_tea",12,560);
book.RegisterGoods("Thinking In C++",20,128);
RegisterGoods函数是怎样知道处理的是tea还是book的数据呢?(this指针)
二、this指针的作用
this指针只在成员函数的参数列表中,对象中并没有。
编译器针对程序员自己设计的类型分三次编译。
第一:识别和记录类体中属性的名称,类型和访问限定,与属性在类体中的位置无关
eg: class CGoods中的Name,Amount,Price,Total_value;
第二:识别和记录类体中函数原型(返回类型+函数名+参数列表),形参的默认值,访问限定。不识别函数体
第三:改写在类中定义函数的参数列表和函数体,改写对象调用成员函数的形式(改写:加入this指针)
示例:
class CGoods
{
private:
char Name[21];
int Amount;
float Price;
float Total_value;
public:
void RegisterGoods(const char *name,int,float);
void CountTotal();
};
void CGoods::RegisterGoods(const char *name,int amount,float price)
{
strcpy(Name,name);//字符拷贝函数
Amount = amount;
Price =price;
}
void CGoods::CountTotal()
{
Total_value=Price * Amount;
}
int main()
{
CGoods tea;
CGoods book;
tea.RegisterGoods("black_tea",12,560);
tea.CountTotal();
book.RegisterGoods("Thinking In C++",20,128);
book.CountTotal();
return 0;
}
改写后的代码:
//只要声明过的对象,都会加入this指针
class CGoods
{
private:
char Name[21];
int Amount;
float Price;
float Total_value;
public:
// void RegisterGoods(CGoods * const this,const char *name,int,float);
void RegisterGoods(const char *name,int,float);
//void CountTotal(CGoods * const this);
void CountTotal();
};
//this指针加入const是为防止this指针置nullptr
//void CGoods::RegisterGoods(CGoods * const this,const char *name,int amount,float price)
void CGoods::RegisterGoods(const char *name,int amount,float price)
{
//this=nullptr; × 空指针不能解引用,此为const的原因
strcpy(Name,name);//字符拷贝函数
this->Amount = amount;
this->Price =price;
}
//void CGoods::CountTotal(CGoods * const this);
void CGoods::CountTotal()
{
this->Total_value = this->Price * this->Amount;
}
int main()
{
CGoods tea;
CGoods book;
tea.RegisterGoods("black_tea",12,560);
// RegisterGoods(&tea,"black_tea",12,560);
tea.CountTotal();
//CountTotal(&tea);
book.RegisterGoods("Thinking In C++",20,128);
// RegisterGoods(&book,"Thinking In C++",20,128);
book.CountTotal();
//CountTotal(&book);
return 0;
}
引用this指针的目地:节省内存空间(方案二比方案一节省空间,同时this指针是方案二可实行的原因)
this指针通过ecx进行传递(速度快),同时也可以不用ecx进行传递,使用_cdecl用c的调用(_cdecl使用栈来传递)
三、全局函数和成员函数的区别
重点是this指针,全局函数无this指针,非静态成员函数有this指针
其间的差别在于一个是程序的需要,一个是编译器的需要
全局函数的参数个数,比局部函数要多一个