在上一讲 C++学习(二):类的定义与对象的创建 中,我们提到了类与对象,那么类是怎么进行数据存储的呢?
类是将数据分为Data和Function两部分来存储的,比如同样的CGoods类,其Data部分是不同对象单独存储,而Function部分是放在一起来调用的。
但这样会有一个问题,我们在实例化以后,如果给不同的对象赋值,比如下面代码中给CGoods实例化为c1和c2,我们的函数 GetName 怎么能知道调用的是谁的 name呢?诚然,我们是在代码中以c1. c2.为前缀说明了应该调用谁的name,所以我们要探究的就是这种机制,看看是怎么运行的。this指针就是解决的这个问题。
这里老师说的有些乱,我按我的理解大体总结成上面的话,但也有些混乱,不知道老师具体想表达啥意思,我觉得都已经拿c1,c2调用了,函数肯定知道到底是谁的name了吧…好在这里不太理解无伤大雅。
class CGoods
{
public: //给用户提供的方法,哪些操作
void RegisterGoods(char name[],int amount,float price); //输入数据
{
strcpy(Name,name); //复制字符串strcpy(dst,src)
Amount = amount;
Price = price;
}
void CountTotal(void); //计算商品总价值
{
Total_value = Amount * Price;
}
void GetName(char name[]); //读取商品名
{
strcpy(name,Name);
}
int GetAmount(void); //读取商品数量
{
return Amount;
}
float GetPrice(void); //读取商品单价
{
return Price;
}
float GetTotal_value(void);
{
return Total_value;
}
private: //有哪些成员(可操作的变量)
char Name[21];
int Amount;
float Price;
float Total_value;
};
void main()
{
CGoods c1,c2; //定义对象——过程就是实例化
c1.RegisterGoods("C++",10,45);
c2.RegisterGoods("Java",5,43);
char name[20];
c1.GetName(name);
cout<<name<<end1;
c2.GetName(name);
cout<<name<<end1;
}
首先,在类中的函数定义以后,this指针就被隐藏定义了,this表示的是当前的对象。
我们先来看C语言中学生结构体的一个例子:
struct Student
{
char name[10];
int age;
char sex[3];
};
void InitStu(Student *st, char n[10], int a, char s[3])
{
strcpy(st->name,n);
st->age = a;
strcpy(st->sex,s);
}
void main()
{
Student st1,st2,st3; //定义三个对象
InitStu(&st1, "大明", 20, "男");
InitStu(&st2, "小红", 18, "女");
InitStu(&st3, "老郭",30,"男");
}
其中的指针st就类似于this指针,指明是哪个对象被调用。换作我们之前的CGoods类,可以看到其实在定义对象以后,原函数在被调用时,已经使用了this指针,只不过将其隐藏了。
我们特意将RegisterGoods里的参数全换成大写的,与类参数定义的一致,则需要靠this函数指明哪一个是底下c1,c2对象的,哪一个是上面参数指代的。
class CGoods
{
public: //给用户提供的方法,哪些操作
void RegisterGoods(char Name[],int Amount,float Price); //输入数据
{
//this
strcpy(this->Name,name); //复制字符串strcpy(dst,src)
this->Amount = Amount;
this->Price = Price;
}
...
private: //有哪些成员(可操作的变量)
char Name[21];
int Amount;
float Price;
float Total_value;
};
void main()
{
CGoods c1,c2; //定义对象——过程就是实例化
c1.RegisterGoods("C++",10,45);
c2.RegisterGoods("Java",5,43);
char name[20];
c1.GetName(name);
cout<<name<<end1;
c2.GetName(name);
cout<<name<<end1;
}
而从上面的过程,我们可以看出C++内部编译时在使用类时的识别过程。第一步先识别类名,即CGoods;第二步再识别数据成员,无论公有私有;第三步才是识别函数和改写函数的过程。
在第三步中,实际编译上程序使用的是注释部分:
class CGoods
{
public:
//void RegisterGoods(CGoods *const this, char Name[], int Amount, int Price)
void RegisterGoods(char Name[],int Amount,float Price); //输入数据
{
strcpy(this->Name,name);
this->Amount = Amount;
this->Price = Price;
}
...
//void CountTotal(CGoods *this)
void CountTotal();
...
void main()
{
CGoods c1,c2;
//RegisterGoods(&c1,"C++",10,12);
c1.RegisterGoods("C++",10,12);
//RegisterGoods(&c2,"Java",5,20);
c2.RegisterGoods("Java",5,20);
char name[20];
//GetName(&c1,name);
c1.GetName(name);
cout<<name<<end1;
}
int a = 10; int b = 20
const int *p = &a ;
int * const p = &a ;
const int * const p = &a ;
以上三种,就像换男朋友和花钱一样。
第一种 const int *p = &a,不能换指向空间中的数据,但可以换指向空间。比如现在p指向的是a,a=10,我们不能让a=20,但我们可以让p指向另一个b,b=20。
第二种 int * const p = &a, const在星号右边,不能换指向空间,但可以换数据。
第三种const int * const p = &a ;既不能更改数据,也不能更改指向空间。