1:成员变量和成员函数分开存储
在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类对象。
案例:我们写一个空类,然后创建一个对象,看看这个空对象占用多大空间。
#include<iostream>
#include<string>
using namespace std;
class Person {
};
void test() {
Person p;
cout << "size of p is: " << sizeof(p) << endl;
}
int main() {
test();
return 0;
}
运行结果可知:
空对象大小为1字节,这是因为编译器为了区分空对象占用内存位置,给每个空对象也会分配一个独一无二的内存地址。
案例:我们写在这个类中添加一个 int 类型的成员变量 m_A。
#include <iostream>
using namespace std;
#include <string>
class Person
{
int m_A;
};
void test01()
{
Person p;
cout << "size of p is: " << sizeof(p) << endl;
}
int main()
{
test01();
return 0;
}
运行结果可知:
包含一个int类型成员变量,这个对象的大小是 4字节。
当我们增加静态成员变量,静态成员函数,非静态成员函数时。
#include<iostream>
#include<string>
using namespace std;
class Person {
int m_A;
static int m_B;
static void func() {};
void func1() {};
};
void test() {
Person p;
cout << "size of p is: " << sizeof(p) << endl;
}
int main() {
test();
return 0;
}
运行结果可知:
不管是静态成员函数,成员韩式,静态成员变量,均不会增加这个对象所占内存大小。
2:this指针
问题
Question : 在C++ 中成员变量和成员函数是分开存储的,每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会公用一块代码,那么问题是:这一块代码是如何区分到底哪个对象调用自己的了 ?
Answer: C++通过提供特殊的对象指针(this指针)来解决上述问题。this指针指向被调用的成员函数所属的对象。 this指针是隐含每一个非静态成员函数的一种指针。 this指针不需要定义,可以直接使用。
this指针用途:
-------》当形参和成员变量同名时,可用this指针来区分。
-------》在类的非静态成员函数中返回对象本身,可使用 return *this 。
案例:现在我们想增加一个成员函数,实现将一个对象的年龄加到另一个对象的年龄上。
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
Person(int age) {
// 1:当形参和成员变量同名时,可用 this指针加以区分。
this->age = age;
}
Person& PersonAddPerson(Person& p) {
this->age += age;
return *this;
}
int age;
};
void test() {
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() {
test();
return 0;
}
运行结果可知:由于每次执行 PersonAddPerson()函数都能返回当前对象,所以可以实现当前对象p2(age的累加)。
3:空指针访问成员函数
在C++中空指针也是可以调用成员函数的,但是也需要注意是否使用到 this指针,如果用到 this指针,那么我们就需要添加判断保证代码的健壮性。
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
void ShowPerson() {
cout << "showPerson enter" << endl;
}
int age;
};
void test() {
// Null空指针是可以调用成员函数的
Person* p = NULL;
p->ShowPerson();
}
int main() {
test();
return 0;
}
如果:成员函数中用到了 this指针,就是不可以的,就需要对this进行判断。
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
void ShowPerson() {
// 事实上属性的前面都是默认添加了 this , 即等同于 this.age 。
if (this == NULL)
{
cout << "当前 person对象为空" << endl;
}
else
{
cout << age << endl;
}
}
int age;
};
void test() {
// Null空指针是可以调用成员函数的,但是一旦成员函数使用了 this 就是不可以的
Person* p = NULL;
p->ShowPerson();
}
int main() {
test();
return 0;
}
4:const修饰成员函数、修饰对象
常函数:
1: 成员函数后加 const,我们称这个函数为 常函数。
2:常函数内不可以修改成员属性。
3:但是成员属性声明时加关键字 mutable ,那么在常函数中依然可以修改。
案例:常函数无法修改普通的成员变量,但是可以修改 mutable修饰的成员变量 。
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
/**
this 指针的本质时一个 指针常量 Person* const this,指针的指向不可以修改,但是指向的值可以修改
如果想让指针指向的值也不可修改,那么就需要声明为 常函数,在函数的参数列表后添加 const
这样 this 指针就变成 : const Person* const this
*/
void ShowPerson() const {
// this = NULL; // 不能修改指针的指向
// this->m_A = 100; //指针this指向的对象的数据也不能修改。
this->m_B = 100; // mutable修饰的变量时可以修改的。
}
int m_A;
mutable int m_B;
};
int main() {
return 0;
}
常对象:
1:声明对象前 添加 const,那么称该对象为 常对象,常对象无法修改成员变量的值
2:如果成员变量添加了 mutable ,那么常对象可以修改这个成员变量的值
3:常对象只能调用常函数,因为普通函数可能会修改 成员变量的值
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
// 常函数
void MyFunc()const {}
// 普通函数
void MyFunc2() {}
// 普通变量
int m_A;
// mutable 可变变量
mutable int m_B;
};
int main() {
const Person person; // 常量对象
person.MyFunc(); // 常量对象只能调用常量函数
person.m_A = 100; // 常量对象不能修改普通成员变量
person.m_B = 100; // 常量对象可以修改 mutable修饰的成员变量
person.MyFunc2(); // 常量对象也不能调用普通函数
return 0;
}