c++对象模型:
各对象的代码区公用
区分对象时根据属性值区分的,对象的方法都是一样的。
上图对象只存储自己的属性,方法共享,这种模型可以大大节省空间。
但是有一个问题,方法(也就是函数)如何区分处理的是哪一个对象
——this指针!
通过this指针判断是哪一个对象
this指针
编译器针对程序员自己设计的类型分三次编译。
第一:识别和记录类体中属性的名称,类型和访问限定,与属性在类体中的位置无关。
如class CGoods中的Name,Amount,Price,Total_value;
第二:识别和记录类体中函数原型(返回类型+函数名+参数列表),形参的默认值,访问限定。不识别函数体。
第三:改写在类中定义函数的参数列表和函数体,改写对象调用成员函数的形式;
例:
#define LEN 21
class CGoods//商品类型
{
private:
char Name[LEN];//商品名称
int Amount;//商品数量
float Price;//商品单价
float Total_value;//商品总价
public:
void RegisterGoods(const char *, int, float);//输入数据
void CountTotal();//计算总价
};
void CGoods::RegisterGoods(const char* name, int amount, float price)
{
strcpy_s(Name,LEN, 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", 20, 128);
book.CountTotal();
return 0;
}
改写后的代码:
//1.识别记录类中的属性名称,类型,访问限定
//char Name[LEN], int Amount, float Price,float Total_value
//2.识别和记录类体中函数原型(返回类型+函数名+参数列表),形参的默认值,访问限定。不识别函数体。
//void RegisterGoods(const char *, int, float);void CountTotal();
//3.改写在类中定义函数的参数列表和函数体,改写对象调用成员函数的形式;
//先改写类中定义的参数列表,接着函数体里的类的成员。
#define LEN 21
class CGoods//商品类型
{
private:
char Name[LEN];//商品名称
int Amount;//商品数量
float Price;//商品单价
float Total_value;//商品总价
public:
//void RegisterGoods(CGoods * const this,const char*,int ,float);//为了防止this指针被改变,加上const,修饰this的指向,只能指向调用此函数的对象
void RegisterGoods(const char *, int, float);//输入数据
//void CountTotal(CGoods * const this);
void CountTotal();//计算总价
};
//void CGoods::RegisterGoods(CGoods *const this,const char* name, int amount, float price)
void CGoods::RegisterGoods(const char* name, int amount, float price)
{
//strcpy_s(this->Name,LEN, name);//Name 是类中的成员
strcpy_s(Name,LEN, name);
//this->Amount = amount;//凡是类中的成员都加上this指针
Amount = amount;
//this->Price = price;
Price = price;
}
//void CGoods::CountTotal(CGoods *const this)
void CGoods::CountTotal()
{
//this->Total_value =this-> Price * this->Amount;
Total_value = Price * Amount;
}
int main()
{
CGoods tea;
CGoods book;
//RegisterGoods(&tea,"black_tea", 12, 560);//通过对象的地址调用
tea.RegisterGoods("black_tea", 12, 560);
//CountTotal(&tea);
tea.CountTotal();
//RegisterGoods(&book,"Thinking", 20, 128);
book.RegisterGoods("Thinking", 20, 128);
//CountTotal(&book);
book.CountTotal();
return 0;
}
引入this指针的目的:
节省空间(但是随之影响的是编译过程变长)
只有类的成员函数才有this指针。
全局函数和类中成员函数的区别:
程序编译时是从上往下依次识别。
1>funa()和func()是全局函数时
解决此问题,可以将funa()函数写在func()函数上面或者在 func()函数之前声明。
void funa();//声明
void func()
{
funa();
}
void funa()
{
}
int main()
{
func();
return 0;
}
2>funa()和func()是类中成员函数时
对象调用类中func函数时
class Node
{
public:
void func()
{
funa();
}
void funa()
{
}
};
int main()
{
Node node;
node.func();
return 0;
}
此时可以编译通过
此时不需要声明也可以编译成功,是因为:
自己设计的类型编译时有三步,第二步时,就会识别和记录类体中函数原型(返回类型+函数名+参数列表),形参的默认值,访问限定,但不会进入函数体,等到第三步进入函数体时,funa()已经被识别记录了,
class Node
{
public:
//void func(Node *const this)
void func()
{
//this->funa();
funa();
}
//void funa(Node *const this)
void funa()
{
}
};
int main()
{
Node node;
//func(&node)
node.func();
return 0;
}