赞
踩
在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;
- }
运行结果可知:
不管是静态成员函数,成员韩式,静态成员变量,均不会增加这个对象所占内存大小。
问题
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的累加)。
在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;
- }
常函数:
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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。