目录
4.3 C++对象模型和this指针
4.3.1 成员变量和成员函数分开存储
在C++中,类内的成员变虽和成员函数分开存储
只有非静态成员变是才属于类的对象上
#include <iostream>
using namespace std;
// 成员变量和成员函数分开存储
class Person {
int age;// 非静态成员变量,属于类的对象上
static int count;// 静态成员变量;不属于类的对象上
void sayHello() { } // 非静态成员函数,不属于类的对象上
static void sayCount() { } // 静态成员函数,不属于类的对象上
};
int Person::count = 0;// 静态成员变量初始化
void test() {
Person p;
//空类体积为1字节
//编译器会给每个空对象分配一个字节的内存空间,是为了区分空对象占用内存空间的位置
//每个空对象有一个独一无二的的内存空间
cout << "size of p = " << sizeof(p) << endl;// 输出:size of p = 1
}
void test2() {
Person p;
cout << "size of p = " << sizeof(p) << endl;// 输出:size of p = 4
}
int main() {
//test();
test2();
//system("pause");// 防止程序结束后直接关闭命令行窗口
return 0;
}
4.3.2 this指针概念
通过4.3.1我们知道在C++中成员变量和成员函数是分开存储的;
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
那么问题是:这一块代码是如何区分那个对象调用自己的呢?
c++通过提供特殊的对象指针,this指针,解决上述问题,
this指针指向被调用的成员函数所属的对象
this指针是隐含每一个非静态成员的数内的一种指针
this指针不需要定义,直接使用即可
this指针的用途:
- 当形参和成员变量同名时,可用this指针来区分
在类的非静态成员函数中返回对象本身,可使用retum*this
#include <iostream>
using namespace std;
//this指针的用途
class Person {
public:
Person(int age){
//age = age;// 这里的age是局部变量,与类成员变量age冲突,所以需要加上this->age = age;
this->age = age;// this指针指向 被调用的成员函数 所属的对象,
}
//
Person &printAge(Person &p){
this->age += p.age;//
return *this;// 返回对象本身;this指向p2的指针,*this指向p2对象
}
int age;
};
//1、解决名称冲突
void test(){
Person p(20);
cout << "age: " << p.age << endl;
//cout << "age: " << this->age << endl; //this指针的用法
}
//2、返回对象本身用 *this
void test2(){
Person p(10);
Person p2(10);
p2.printAge(p);
p2.printAge(p).printAge(p).printAge(p);// 链式调用
cout << "p.age: " << p.age << endl;
cout << "p2.age: " << p2.age << endl;
}
int main() {
//test();
test2();
return 0;
}
4.3.3 空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性
示例:
#include <iostream>
using namespace std;
// 空指针访问成员函数
class Person {
public:
void showClassName() {
cout << "this is Person class" << endl;
}
void showAge() {
// 报错:访问空指针 NULL
if (this == NULL) {
cout << "this person is unknown" << endl;
return;
}
cout << "this person is " << this->m_age << " years old" << endl;
}
int m_age;
};
void test() {
Person *p = NULL;
p->showClassName(); // 空指针访问成员函数
p->showAge(); // 空指针访问成员函数
}
int main() {
test();
system("pause");
return 0;
}
4.3.4 const修饰成员函数
常函数:
- 成员函数后加const后我们称为这个函数为常函数
- 常函数内不可以修改成员属性
- 成员属性声明时加关键字mutable后,在常函数中依然可以修改
常对象:
- 声明对象前加const称该对象为常对象
- 常对象只能调用常函数
示例:
#include <iostream>
using namespace std;
// 常函数
class MyClass {
public:
// this指针的本质:是指针常量,指针的指向不能被修改
// const修饰成员函数:不能修改this指针指向的对象,也不能修改this指针指向的对象的成员变量
// 在成员函数后面加 const 关键字,修饰的是this指向,让指针指向的值不可以被修改
void myFunc() const {
//this->myData = 10;// 错误:
//this = NULL; // 错误:常函数不能修改this指针指向的对象;this指针不可以修改指针的指向
this->myData_2 = 20; // 正确:常函数可以修改this指针指向的对象的成员变量
}
void myFunc2() {
}
int myData;
mutable int myData_2;// 关键字mutable;特殊变量,即使在常函数中,也能修改
};
void test() {
MyClass obj;
obj.myFunc();
}
// 常对象
void test2() {
const MyClass obj;// 在对象前面加 const 关键字,变为常对象
//obj.myData = 10; // 错误:常对象不能修改成员变量
obj.myData_2 = 30; // 正确:常对象可以修改mutable成员变量
// 常对象只能调用常函数
obj.myFunc();
//obj.myFunc2();// 常对象,不能调用普通成员函数,因为普通成员函数可以修改属性
}
int main() {
return 0;
}