1.指针定义
定义语法:类型 * 指针变量 如:int* p1; int* p1 = &a
但是定义指针时,要指明指针指向,不然很危险,int* p1 = &a,其中&为取址符
无效指针或野指针:int* p1
没有指名指向的为无效指针或野指针,野指针很危险,不知道要指向什么时,可以定义为空指针
空指针:int* np = nullptr;
void * 指针: 一般来说,指针的类型必须和指向的对象类型匹配,否则就会报错。不过有一种指针比较特殊,可以用来存放任意对象的地址,这种指针的类型是void*。void* 指针表示只知道“保存了一个地址”,至于这个地址对应的数据对象是什么类型并不清楚。所以不能通过 void* 指针访问对象;一般 void* 指针只用来比较地址、或者作为函数的输入输出。
指向指针的指针:指针本身也是一个数据对象,也有自己的内存地址。所以可以让一个指针保存另一个指针的地址,这就是“指向指针的指针”,有时也叫“二级指针”;形式上可以用连续两个的星号**来表示。类似地,如果是三级指针就是***,表示“指向二级指针的指针”。
int i = 1024;
int* pi = &i; // pi是一个指针,指向int类型的数据
int** ppi = π // ppi是一个二级指针,指向一个int* 类型的指针
如果需要访问二级指针所指向的最原始的那个数据,应该做两次解引用操作。
常见的指针操作:
int a = 12;
int b = 100;
int* p = &a //定义指针p指向a的地址
p = &b //指针p改变为指向b的地址
*p = 25 //指向的整型数据b改为25
cout << "b = " << b << endl; //25
2.常量指针 (const int* pc)
指针指向的是一个常量,所以只能访问数据,不能通过指针对数据进行修改。不过指针本身是变量,指针的指向是可以改变的
const int c = 10, c2 = 56;
//int* pc = &c; // 错误,类型不匹配
const int* pc = &c; // 正确,pc是指向常量的指针,类型为const int *
pc = &c2; // pc可以指向另一个常量
int i = 1024;
pc = &i; // pc也可以指向变量,pc的指向可以变
*pc = 1000; // 错误,不能通过pc更改数据对象
3. 指针常量(int* const p)
指针本身是一个常量,就意味它保存的地址不能更改,也就是它永远指向同一个对象;而数据对象的内容是可以通过指针改变的。
int* const cp = &i;
*cp = 2048; // 通过指针修改对象的值
//cp = &c; // 错误,不可以更改cp的指向
const int* const ccp = &c; // ccp是一个指向常量的常量指针
1.this指针
理论上来讲,在类的内部,访问当前类中的(非态)成员的时候,应该都使用this->来访问。
实际上,绝大多数的情况下,this->都是可以省略不写的。
this在什么情况下不能省略?
如果在一个函数内,出现了局部变量和属性同名字的情况,为了区分局部变量和属性,需要显式使用this->来访问属性。
this指针是隐含每一个非静态成员函数内的一种指针,即每一个非静态成员函数内的一种指针都有一个this指针
this指针的本质是 指针常量(* const this)指针的指向不能修改
this指针的用途:
- 当形参和成员变量同名时,可用this指针来区分
- 在类的非静态成员函数中返回对象本身,可使用return *this
class Person
{
public:
int age;
Person(int age)
{
this->age = age;
当形参和成员变量同名时,可用this指针来区分,this指向的age为成员变量,而非形参,此
时this不可省略
}
Person& PersonAddPerson(Person p)
{
this->age += p.age;
//返回对象本身,此时要用引用Person&接收
return *this;
}
};
void test01()
{
Person p1(10);
cout << "p1.age = " << p1.age << endl;
Person p2(10);
p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
cout << "p2.age = " << p2.age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
2.空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性
//空指针访问成员函数
class Person {
public:
void ShowClassName() {
cout << "我是Person类!" << endl;
}
void ShowPerson() {
if (this == NULL) {
return;
}
cout << mAge << endl;
}
public:
int mAge;
};
void test01()
{
Person * p = NULL;
p->ShowClassName(); //空指针,可以调用成员函数
p->ShowPerson(); //但是如果成员函数中用到了this指针,就不可以了
}
int main() {
test01();
system("pause");
return 0;
}
3. const修饰成员函数
常函数:
- 成员函数后加const后我们称为这个函数为常函数
- 常函数内不可以修改成员属性
- 成员属性声明时加关键字mutable后,在常函数中依然可以修改
- 常函数,不允许调用普通函数,只能调用其他常函数
常对象:
- 声明对象前加const称该对象为常对象
- 常对象可以读取任意属性的值,但不允许修改
- 常对象只能调用常函数,不能调用普通成员函数,因为普通成员函数可以修改属性
注意常函数与常对象const的位置
const Person person; //常对象 const在头
void ShowPerson() const {
}
//常函数,const在形参后面
eg:
class Person {
public:
Person() {
m_A = 0;
m_B = 0;
}
//this指针的本质是一个指针常量,指针的指向不可修改
//如果想让指针指向的值也不可以修改,需要声明常函数
void ShowPerson() const {
//const Type* const pointer;
//this = NULL; //不能修改指针的指向 Person* const this;
//this->mA = 100; //但是this指针指向的对象的数据是可以修改的
//const修饰成员函数,表示指针指向的内存空间的数据不能修改,除了mutable修饰的变量
this->m_B = 100;
}
void MyFunc() const {
//m_A = 10000; 常函数,不能修改
}
public:
int m_A;
mutable int m_B; //可修改 可变的
};
//const修饰对象 常对象
void test01() {
const Person person; //常量对象
cout << person.m_A << endl;
//person.mA = 100; //常对象不能修改成员变量的值,但是可以访问
person.m_B = 100; //但是常对象可以修改mutable修饰成员变量
//常对象访问常函数
person.MyFunc();
}
int main() {
test01();
system("pause");
return 0;
}