目录
一、成员变量和成员函数分开存储
二、this指针
三、空指针访问成员函数
四、const修饰成员函数
常函数:
常对象:
一、成员变量和成员函数分开存储
在C++中,类内的成员变量和成员分开存储
只有非静态成员变量才属于类的对象上
示例:
#include<iostream>
#include<string>
using namespace std;
// 成员变量 与 成员函数 是分开存储的
class student {
};
class person {
int a; // 非静态的成员变量 属于类的对象上
static int b; // 静态的成员变量 不属于类的对象上
void func() {} // 非静态成员函数 不属于类的对象上
static void func2() {} // 静态成员函数 不属于类的对象上
};
// 初始化
int person::b = 0;
void test01()
{
student s;
// c++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
// 每个空对象也有独一无二的内存地址
// 空对象的字节空间是 1
cout << "studednt 类的对象占多少字节空间 " << sizeof(s) << endl;
}
void test02()
{
person p1;
// 不是空的就按照里面的数据类型分配空间
cout << "p1 类的对象占多少字节空间 " << sizeof(p1) << endl;
}
int main()
{
test01();
test02();
return 0;
}
运行结果:
二、this指针
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
那么问题来了:这一块代码是如何区分哪个对象在调用呢?
C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象
this指针指向的是被调用的成员函数所属的对象
this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接调用即可
this指针的用途:
1. 当形参和成员变量同名时,可以用this指针来区分
2. 在类的非静态成员函数中返回对象本身,可以使用 return *this
示例:
#include<iostream>
#include<string>
using namespace std;
// 2. 返回对象本身时用return *this
class person {
public:
person(int age)
{
// 1. 解决名称冲突
this->age = age;
// this指针指向的是被调用的成员函数 所属的对象
}
void person_add_age(person& p)
{
this->age += p.age;
}
person& person_add_Age(person& p)
{
this->age += p.age;
// this 指向p4的指针,而*this指向的就是p4这个对象本体
return *this;
}
// 以值的形式返回
person person_Add_Age(person& p)
{
this->age += p.age;
// this 指向p4的指针,而*this指向的就是p4这个对象本体
return *this;
}
int age;
};
// 1. 解决名称冲突
void test01()
{
person p1(18);
cout << "p1的年龄 " << p1.age << endl;
}
void test02()
{
person p2(10);
person p3(10);
p3.person_add_age(p2);
cout << "p2的年龄 " << p2.age << endl;
cout << "p3的年龄 " << p3.age << endl;
person p4(10);
// 函数的返回值还是p4本身可以继续调用函数
p4.person_add_Age(p2).person_add_Age(p2);// 链式编程思想
cout << "p4的年龄 " << p4.age << endl;
person p5(20);
p5.person_Add_Age(p5).person_Add_Age(p5);
cout << "p5的年龄 " << p5.age << endl;
}
int main()
{
test01();
test02();
return 0;
}
运行结果:
三、空指针访问成员函数
c++中空指针也是可以调用成员函数的,但是要注意有没有this指针
如果用到了 this 指针,需要加以判断保证代码的健壮性。
示例:
#include<iostream>
#include<string>
using namespace std;
// 空指针调用成员函数
class person{
public:
void show_class_name()
{
cout<<"这是person的一个类"<<endl;
}
void show_person_age()
{
if(this==NULL)
return ; // 如果this为NULL直接return掉
cout<<"age是"<<this->age<<endl;
// 报错的原因是传入的指针为空指针(NULL)
}
int age;
};
void test01()
{
person *p = NULL;
p->show_class_name();
p->show_person_age();
// 空指针可以调用成员函数
}
int main()
{
test01();
return 0;
}
运行结果:
报错提示:
四、const修饰成员函数
-
常函数:
- 成员函数 后加 const 后我们称这个函数为常函数
- 常函数内不可以修改成员属性
- 成员声明时加关键字 mutable 后,在常函数中依然可以修改
-
常对象:
- 声明对象前加 const 称该对象为常对象
- 常对象只能调用常函数
示例:
#include<iostream>
#include<string>
using namespace std;
// 常函数
class person {
public:
// this指针的本质是 指针常量 指针的指向是不可以修改的
// this在这里的意思是 Person * const this; (指针的指向不可以改)
// 在成员函数后面加 const ,修饰的是this指向,让指针指向的值也不可以修改。
void show_person() const // (再加一个const那么this指针的指向和值都不可以改变)
// 相当于常函数
{
this->b = 100;
}
void func()
{
}
int a;
// +mutable 后可以修改值
mutable int b; // 特殊变量 即使在常函数中,也可以修改这个值
};
void test01()
{
person p;
p.show_person();
}
// 常对象
void test02()
{
const person p1; // 在对象前 + const 变为常对象
p1.b = 100; // b是特殊值,在常对象下也可以修改
// 常对象只能调用常函数
p1.show_person();
// 常对象不能调用普通成员函数
// p1.func();
// 因为普通成员函数可以修改属性
}
int main()
{
test01();
test02();
return 0;
}
运行结果: