在上篇C++类和对象的博客中,我们讲述了析构函数、拷贝构造函数、浅拷贝和深拷贝的内容,我们紧接上文,开始讲述接下来的文章。
目录
1.this指针
1.1引入
1.2内容
1.3特征
1.4用法
2.静态成员
2.1内容
2.2静态数据成员
2.3静态成员函数
2.4实践
1.this指针
1.1引入
了解this指针之前,我们先来看一段代码:
#include<iostream>
class A {
private:
int x, y, z;
public:
A(int xvalue = 0, int yvalue = 0, int zvalue = 0) {
x = xvalue;
y = yvalue;
z = zvalue;
}
void show() { // const A * this
std::cout << "(" << x << "," << y << "," << z << ")\n";
}
};
int main() {
A a1(1, 1, 1), a2(2, 2, 2);
a1.show();
system("pause");
return 0;
}
毫无疑问这是一段十分简单的代码,它的输出结果即是对象a1的打印。问题是:我们同时定义了a1和a2两个对象,但是我们在打印函数show中并未对具体的对象加以区分,那么show怎么清楚它需要打印对象a1而不是对象a2。
这并非是一个简单的a1.show()就可以阐述清楚的,虽然凭借这样的语法格式,我们可以很明显的理解出是对a1对象的打印,但是我们需要细究其中的底层逻辑,即编译器是怎么理解这一段代码的。
1.2内容
于是,为了面对上述问题,C++引入this指针来处理这种情况,即C++编译器会为每一个“非静态成员变量的成员函数”添加一个隐藏指针,这个指针便是this指针。
在函数被调用中,this指针会去指向当前调用函数运行的对象,并且在接下来函数体中所有类的成员变量操作,都是通过this指针去访问的。这是一个透明操作,即整个过程并不需要用户去完成和传递,编译器会自动完成。
1.3特征
this指针存在以下常见的四种特征:
- this指针被const修饰,意味着在成员函数中,它不能被赋值;
- this指针只能在成员函数内部使用;
- this指针本质上是非静态成员函数的形参,当对象调用成员函数时,会将对象的地址作为实参传递给this形参,所以对象中不储存this指针;
- this指针是非静态成员函数中第一个隐藏指针形参,一般由编译器通过寄存器(VS中是ECX)自动传递。
1.4用法
this指针的用法由很多,在此我简单讲述两种:一种是可以用来区分成员和非成员;另一种是可以用来返回当前对象的引用,具体我们通过下述代码理解:
#include<iostream>
class A {
private:
int x, y, z;
public:
A(int x = 0, int y = 0, int z = 0) {
//使用this指针区分成员和非成员,如此我们可以不关注成员和非成员名称的一致性。
this->x = x;
this->y = y;
(*this).z = z;
}
void show() { // const A * this
std::cout << "(" << x << "," << y << "," << z << ")\n";
}
A& ret() {
return *this;//返回当前对象的引用
}
};
int main() {
A a1(1, 1, 1), a2(2, 2, 2);
(a1.ret()).show();
system("pause");
return 0;
}
最后的执行结果依旧是对象a1的内容打印。
2.静态成员
2.1内容
在有些时候我们需要对全局数据加以统计,此时采用全局变量不一定安全,并且会破坏C++的封装,因此我们引入静态成员的概念来完成对该任务的实现,不过静态成员的作用远不止于此。‘
当我们在使用static关键字将类成员定义为静态成员时,这便意味着无论后续定义多少份该类的对象,此静态成员只会存在一份(类的范围内所有对象共享该数据),静态成员可以声明为公有的、私有的或是保护的。
接下来根据静态关键字可以修饰的不同对象类型,即数据成员和函数成员,我们将其分开讲述。
2.2静态数据成员
静态数据成员不属于任何一个对象,它在程序编译时创建并初始化,所以它在该类的任何对象初始化之前便已经完成了创建。
2.3静态成员函数
静态成员函数可以在类中定义也可以在类外定义(类外定义不用static前缀),它一般用于访问全局变量或是一个类中的静态数据成员,可以用于建立任何对象之前处理静态数据成员,并且对于静态成员函数而言,它不能访问类中的非静态数据成员,它也不存在this指针。
2.4实践
了解完内容之后,我们来通过具体的代码进行深入理解。
#include<iostream>
class Student {
public:
//静态成员:人数和总分
static int total;
static double sum;
//构造函数
Student(double score = 0.0) {
this->score = score;
//每次创建对象则人数和总分随之增加
total++;
sum += score;
}
//静态成员函数,访问静态成员
static int get_total() {
return total;
}
static double get_sum() {
return sum;
}
private:
//个人得分
double score;
};
//静态成员需在类外完成初始化
int Student::total = 0;
double Student::sum = 0;
int main() {
std::cout << "before:\n" << "人数:" << Student::get_total() << "," << "总分:" << Student::get_sum() << std::endl;
Student s1(90);
Student s2(91);
Student s3(92);
std::cout << "final:\n" << "人数:" << Student::get_total() << "," << "总分:" << Student::get_sum() << std::endl;
return 0;
}
最后我们得到执行结果为:
这便很好的说明了静态成员的内容。