C++对象模型和this指针学习案例
1.成员变量和成员函数分开存储
#include <iostream>
using namespace std;
// 空类的对象 size 为1
class NullClass{
};
class Person{
int m_A; // 非静态成员变量 属于类的对象上
};
class All{
int m_A; // 非静态成员变量 属于类的对象上
static int m_B; // 静态成员变量 不属于类的对象上
void func(){} // 非静态成员函数 不属于类的对象上
static void func2(){} // 静态成员函数 不属于类的对象上
};
int All::m_B = 0;
void test01(){
NullClass p;
cout << "size of 空类对象 p = "<< sizeof(p) << endl;
Person q;
cout << "size of 包含非静态成员变量的对象 q = "<< sizeof(q) << endl;
All a;
cout << "size of 包含所有的对象 a = "<< sizeof(a) << endl;
}
int main(){
test01();
}
2.this指针概念
#include <iostream>
using namespace std;
// this指针
// 用来指向被调用的成员函数所属的对象
// 用途1: 解决形参和属性名冲突
// 用途2: 在类的非静态成员函数中返回对象本身,可使用return *this
class Person{
public:
Person(int age){
// age = age; // 形参和属性名冲突
this->age = age; // 1,使用this指针解决冲突
}
// 返回类型时Person时, 是以值的方式返回,会调用拷贝构造函数,返回一个新的p2
Person FalsePersonAddAge(Person p){
this->age += p.age;
return *this;
}
// 返回类型时Person&时, 是以引用的方式返回,返回的是p2本身
Person& TruePersonAddAge(Person p){
this->age += p.age;
return *this; // 2.在类的非静态成员函数中返回对象本身,可使用return *this
}
int age;
};
void test01(){
Person p1(10);
cout << "p1 age = " << p1.age << endl;
Person p2(10);
p2.FalsePersonAddAge(p1).FalsePersonAddAge(p1).FalsePersonAddAge(p1); // 链式编程思想
cout << "p2 age = " << p2.age << endl; // 20
Person p3(10);
p3.FalsePersonAddAge(p1).FalsePersonAddAge(p1).FalsePersonAddAge(p1); // 链式编程思想
cout << "p3 age = " << p3.age << endl; // 40
}
int main(){
test01();
}
3.空指针访问成员函数
#include <iostream>
using namespace std;
// C++中 空指针也可以调用成员函数,但要注意成员函数中有没有用到this指针
// 如果用到了,需要在成员函数中加以判断,保证代码的鲁棒性
class Person{
public:
void showClassName(){
cout << "Person 类" << endl;
}
void showPersonAge(){
// 报错原因是因为传入指针为NULL,因此要加上判断, 这样就不会报错了
if(this != NULL){
cout << "age = " << m_age << endl; // 编译器默认会加上 this->m_age
}
}
int m_age;
};
void test01(){
// 空指针, 类型为Person *
Person * p = NULL;
p->showClassName();
p->showPersonAge();
}
int main(){
test01();
}
4.const修饰成员函数
#include <iostream>
using namespace std;
// 常(成员)函数
// 1.成员函数后加const 表示这个函数为常成员函数
// 2.常成员函数内不可以修改成员属性
// 3.但是如果成员属性声名时加上mutable关键字,在常成员函数中依然可以修改
// 常对象
// 1. 声名对象时加const修饰 表示这个对象为常对象
// 2. 常对象只能调用常成员函数
class Person{
public:
void showPerson() const // 常成员函数
{
// m_A = 100;
// 报错,不允许修改 相当于this—>m_A = 100
// this指针本质是指针常量,指向不可以修改,但指向的值可以修改,相当于Person * const this
// 成员函数加上const,修饰的是this指针的指向,相当于 const Person * const this
}
int m_A;
};
class Person2{
public:
void showPerson2() const // 常成员函数
{
m_A = 100; // 不报错,允许修改
cout << "m_A = " << this->m_A << endl;
}
void func(){
}
mutable int m_A; // 加上mutable关键字
};
void test01(){
const Person2 p; // 常对象
p.m_A = 0;
p.showPerson2();
// p.func(); // 报错,常对象不能调用除常函数外的函数
// 因为func()可以对属性进行修改,如果常对象能调用除常函数外的函数,那么就会间接修改属性,这样是不行的
}
int main(){
test01();
}