文章目录
- 1.this指针引入
- 2.this指针的特性
- 3.静态成员
- 3.1.C语言中static的基本用法
- 3.2.C++中的static关键字
1.this指针引入
class student
{
public:
student(const string& name){
_name = name;
}
void print(){
// _name<=>this->_name<=>(*this)._name
// 说一下:指针用箭头->返回成员(如:结构体,this->_name); 对像用.来访问成员
cout << "我是" << _name << endl;
}
private:
string _name;
};
int main()
{
student stu1("张三"); stu1.print();
student stu2("李四"); stu2.print();
return 0;
}
结果输出:
我是张三
我是李四
C++编译器为每个"非静态的成员函数",增加了一个隐藏的this指针,然该指针指向当前对象(函数运行时调用该函数的对象),来完成对"成员变量"的操作! 输出张三,说明访问stu1
对象中村存储的数据"张三";数据李四,方式的是stu2
对象域中的数据,根据this指针代表的对象不同,访问到的数据就会不同。
2.this指针的特性
this指针本质上是成员函数的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参; this在成员函数开始执行前构造,在执行结束后销毁。那this指针存放在哪里?
class number
{
public:
void sum(int x, int y){
_result = x + y;
}
private:
int _result = 0;
};
int main()
{
number num;
num.sum(1, 2);
return 0;
}
在32位机器上,通过上面的代码对num.sum(1, 2);
反汇编:
num.sum(1, 2);
00671907 push 2
00671909 push 1
0067190B lea ecx,[num]
0067190E call number::sum (06712F3h)
可以看的,在call调用sum成员函数之前编译器ecx计数寄存器自动传递this指针;一般来说this指针是在栈上的,VS将对象的num的地址存放到ecx中!this指针存放到ecx中;不同的编译器可能会有不同。
this指针是:类的类型 * const
所以在成员函数中不能对this指针做修改
class number
{
public:
void sum(int x, int y){
this = nullptr; // 不允许,也不允许&this(想要查看this的地址)
_result = x + y;
}
private:
int _result = 0;
};
另外,this指针是编译器自动的传递,而且会占用参数的第一个位置,我们不用显示的传递,也不能在成员函数中显示的接收,但是在成员函数中显示的使用 如:this->_result
class number
{
public:
void sum(number const& this,int x, int y){
_result = x + y;
}
private:
int _result = 0;
};
当然我们可以使用this来区分两种定义对象的不同方式:
class student
{
public:
student(const string& name) {
_name = name;
}
void print() {
int num = 1;
char* ptr = (char*)malloc(1);
printf("num的地址:%p,malloc的地址:%p,this指向对象的地址:%p\n", &num,ptr,this);
cout << "我是" << _name << endl;
}
private:
string _name;
};
int main()
{
student stu1("张三");
stu1.print();
student* stu2 = new student("李四");
stu2->print();
return 0;
}
输出结果:
num的地址:009DF63C,malloc的地址:00E4F618,this指向对象的地址:009DF7B8
我是张三
num的地址:009DF63C,malloc的地址:00E4B3C8,this指向对象的地址:00E4E178
我是李四
为什么要做上面的这个实验,我之前老想不明白,害,太菜了!其实new的底层是malloc,是在堆上开辟空间!
this指针存放在哪里,this指针可以为空吗
class A
{
public:
void Print(){
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
// 上面的正常运行
class A
{
public:
void PrintA(){
cout << _a << endl; //显示写:this->_a,this指针为nullptr,解引用,程序崩溃
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
return 0;
}
上面两段代码,在main函数中,都没有问题,p对象访问成员函数,因为Print成员函数的地址不在对象中,不会发生解引用!
3.静态成员
3.1.C语言中static的基本用法
在C语言中,static修饰的局部的变量可以,可以改变其是生命周期,使其生命周期随程序;对静态的全部变量和函数,限制在本源文件内使用;也就是说如果static修饰全局的变量或函数,跨一个源文件就不能使用!
下图是没有修饰的,可以跨源文件使用:
3.2.C++中的static关键字
C++中声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化,类中的只是声明
#include<iostream>
using namespace std;
void sum(int x, int y) {}
int g_val = 5;
class Math
{
public:
const static int _num = 0; // 这样在类内定义静态成员变量也是可以的,不推荐
static void sum(int x, int y) {}
private:
static int _result; // 这里只是声明!
};
int Math::_result = 5; // 定义并初始化!
int main()
{
printf("全局的变量:%p, Math类中的静态函数:%p\n", sum, Math::sum);
printf("全局的变量:%p, Math类中的静态变量:%p\n", &g_val, &Math::_num);
return 0;
}
输出结果:
全局的变量:003A12B7, number类中的静态函数:003A1073
全局的变量:003AA000, number类中的静态变量:003AA1A8
静态成员变量:会被类的所有对象共享,包括派生类的对象;static修饰变量(全局,局部,成员)和全局变量一样放在全局的数据区在来编译器编译的时候就会开辟空间并完成初始化!(有资料说,静态成员变量因为构造函数的问题,在使用到相关代码才会初始化,但是我通过调试是在加载的时候就初始化的,害!)
静态成员函数:静态成员函数没有隐藏的this指针,不能访问任何非静态成员;但是非静态函数却能任何静态成员;
类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问,当然. 静态成员也是类的成员,受public、protected、private 访问限定符的限制!
实现一个类,计算程序中创建出了多少个类对象
class A
{
public:
A() { ++_scount; }
A(const A& t) { ++_scount; }
~A() { --_scount; }
static int GetACount() { return _scount; }
private:
static int _scount;
};
int A::_scount = 0;