在C++中,类内的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上
空对象所占用的内存空间
C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置。每个空对象也应该有一个独一无二的内存地址。
#include
using namespace std;class Person
{
public:};void test01()
{Person p;cout << sizeof(p) << endl; // 空对象占用一个字节
}int main()
{test01();system("pause");return 0;
}
1
请按任意键继续. . .
非空对象所占用的内存空间
1.非静态成员变量,属于类的对象上;
2.静态成员变量、静态成员函数和非静态成员函数,不属于类的对象上。
#include
using namespace std;class Person
{
public:int m_A;static int m_B;void func() {}static void func1() {}
};
int Person::m_B = 0;void test02()
{Person p1;cout << sizeof(p1) << endl;
}int main()
{test02();system("pause");return 0;
}
4
请按任意键继续. . .
非静态成员变量是存放在对象上的,而静态成员变量和静态成员函数是所有对象共用的。只有非静态成员函数是不被所有对象共用,因此,在对象调用这个函数的时候,需要进行一个区分。
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
那么这一块代码是如何区分那个对象调用的是自己的函数的呢?
C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象
。
this指针是隐含在每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可
this指针的用途
:
#include
using namespace std;class Person
{
public:Person(int age){// this指针指向 被调用的成员函数 所属的成员函数this->age = age; //当形参与成员变量同名时,this指针可以用来区分形参与成员变量//age = age; //形参与成员变量同名,输出会出现错误(乱码)}int age;
};// 1. 解决名称冲突
void test01()
{Person p(18);cout << "年龄 = " << p.age << endl;
}int main()
{test01();system("pause");return 0;
}
年龄 = 18
请按任意键继续. . .
在类的非静态成员函数中返回对象本身,可用return *this
#include
using namespace std;class Person
{
public:Person(int age){this->age = age; //当形参与成员变量同名时,this指针可以用来区分形参与成员变量}// 函数返回值类型如果为void(无符号类型),则不能进行多次加操作,进行多次加操作则会报错(返回的不是对象,不能调用成员函数)// 函数返回的如果是值,则会出现尽管是链式相加,但是结果还是两个数相加的结果(18+18=36 18+18=36)// 函数只有返回的是引用,才能实现链式相加(18+18+18=54)Person& PersonAddPerson(Person &p){this->age += p.age;return *this;}int age;
};// 2. 返回对象本身
void test02()
{Person p1(18);Person p2(18);// 链式编程思想p2.PersonAddPerson(p1).PersonAddPerson(p1);cout << "p2的年龄 = " << p2.age << endl;
}int main()
{test02();system("pause");return 0;
}
p2的年龄 = 54
请按任意键继续. . .
【注意】
:
???
;C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性
#include
using namespace std;
//空指针调用成员函数
class Person
{
public:void showClassName(){cout << "this is Person Class" << endl;}void showPersonAge(){// 报错(读取访问权限冲突),原因是传入的指针为空指针,未指向任何实体,因此不能够访问属性// 为了提升代码的健壮性,可以写一个if else语句,这样尽管不能访问,但是可以直接退出,不会出现报错。if (this == NULL){return;}cout << "PersonAge is " << this->m_Age << endl;}int m_Age;
};void test01()
{Person* p = NULL;p->showClassName();p->showPersonAge();
}int main()
{test01();system("pause");return 0;
}
this is Person Class
请按任意键继续. . .
常函数
:
常对象
:
常函数
#include
using namespace std;class Person
{
public:// this指针的本质是指针常量 只能改变指针指向变量的值,但是不能改变指针的指向// const Person * const this// 在成员函数后面加const,修饰的是this指针,指针指向的值也不能修改了void showPersonName() const{this->m_A = 100; // 特殊变量(mutable)成员变量可以在常函数中修改//this->m_B = 100; //报错,常函数内不能修改成员属性//this = NULL; //报错,this指针只能改变指针指向变量的值,不能改变指针的指向}// 成员属性的申明时前加关键字mutable后,成员属性在常函数中仍能修改mutable int m_A;int m_B;
};
// 常函数
void test01()
{Person p;p.showPersonName();cout << p.m_A << endl;
}int main()
{test01();system("pause");return 0;
}
100
请按任意键继续. . .
常对象
#include
using namespace std;class Person
{
public:void showPersonName() const{this->m_A = 100; }void func(){cout << "常对象不能调用普通成员函数!" << endl;}mutable int m_A;int m_B;
};// 常对象
void test02()
{const Person p1; // 在对象前加一个const则得到一个常对象,常对象不允许修改一般的成员属性p1.m_A = 200; //常对象可以修改特殊的成员属性(mutable成员属性)cout << p1.m_A << endl;p1.showPersonName(); cout << p1.m_A << endl;//p1.m_B = 100; //报错,常对象也不能修改一般的成员属性//p1.func(); //报错,常对象不能调用普通成员函数,因为其可以修改属性
}
int main()
{test02();system("pause");return 0;
}
200
100
请按任意键继续. . .