1. 成员变量和函数的存储
c++中“数据”和“处理数据的操作(函数)”是分开存储的
- c++中的非静态数据成员直接内含在类对象中,就像c struct一样。
- 成员函数(member function)虽然内含在class声明之内,却不出现在对象中。
- 每一个非内联成员函数(non-inline member function)只会诞生一份函数实例.
空类的大小是1,不是0
// 1. 空类的大小是1,不是0
class Maker
{
};
void test01()
{
cout << sizeof(Maker) << endl; // 1
Maker *m = new Maker[20]; // 为什么空类是1,因为编译器从内存更好区分对象
}
类的成员函数、静态成员函数、静态成员变量不占用类的大小
class Maker2
{
public:
public:
// 类的成员函数 不占用类的大小
void func()
{
}
// 类的静态成员函数 不占用类的大小
static void func2()
{
}
// 类的静态成员变量 不占用类的大小
static int a;
};
void test02()
{
cout << sizeof(Maker2) << endl;
}
普通成员 占用类的大小
// 3. 普通成员 占用类的大小
// 4. 类的成员中,成员函数和成员变量是分开存储的
class Maker3
{
public:
// 类的成员函数和成员变量是分开存储的,那为什么类的成员函数可以访问成员变量?
// 编译器内部把成员变量的空间的指针 传入成员函数中 void func(this *p)
void func()
{
b = 20;
cout << b << endl;
}
static void func2()
{
}
static int a;
int b; // 普通成员 暂用类的大小 4 字节
int c; // 4 字节
};
int Maker3::a = 100;
void test03()
{
cout << sizeof(Maker3) << endl; // 8
Maker3 m;
m.func();
}
总结:
1.空类的大小是1,不是0
2.类的成员函数、静态成员函数、静态成员变量不占用类的大小
3.普通成员 占用类的大小
4.类的成员中,成员函数和成员变量是分开存储的
2. this指针
c++的数据和操作也是分开存储,并且每一个非内联成员函数(non-inline member function)只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
那么问题是:这一块代码是如何区分那个对象调用自己的呢?
c++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象。
c++规定,this指针是隐含在对象成员函数内的一种指针。当一个对象被创建后,它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址,也就是说虽然我们没有写上this指针,编译器在编译的时候也是会加上的。因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果。
this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的函数成员。一般情况下,并不写this,而是让系统进行默认设置。
this指针永远指向当前对象
成员函数通过this指针即可知道操作的是那个对象的数据。this指针是一种隐含指针,它隐含于每个类的非静态成员函数中。this指针无需定义,直接使用即可。
注意:静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。
2.1 this指针的作用
-
当形参名和成员变量名相同时,用this指针区分
-
在类的非静态成员函数中返回对象本身,可使用return *this.
class Maker2
{
public:
int id;
public:
// 1.当形参名和成员变量名相同时,用this指针区分
Maker2(int id)
{
this->id = id;
}
// 2. 返回对象的本身
Maker2 &getMaker2()
{
return *this; // 运算符重载时有用
}
};
2.2 this指针拓展
this指针指向的空间有没有存储静态成员变量?
没有,静态成员变量是属于类,所有对象共有的
class Maker3
{
public:
static void func()
{
// this->a = 200; //报错
}
public:
static int a;
};
int Maker3::a = 10;
void test02()
{
Maker3 m;
m.func();
}
this指针的指向可以改变吗?
this指针是指向对象的存储空间,是不可以改变的,也就是说this是Class* const this
总结:
1.每个对象都有一个隐藏的this指针,但不属于对象,是编译器添加的
2.编译器会把this指针传入成员函数内
3.this指针永远指向当前对象
4.this指针的作用:1)当形参名和成员变量名相同时,用this指针区分。2)返回对象的本身
5.this指针指向的空间没有存储静态成员变量
6.this指针的指向不能改变
3. const修饰成员函数(常函数)
用const修饰的成员函数被称为常函数
- 用const修饰的成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量
- 当成员变量类型用mutable修饰时例外
class Maker
{
public:
Maker(int id, int age)
{
this->id = id;
this->age = age;
score = 100;
}
// 常函数
// 1. 在函数的()后面加上const,就是常函数
void printMaker() const
{
// id = 100; // 2.常函数体内不能修改普通成员变量
// 3. const修饰的是this指针指向的空间中的变量,不能改变
// Maker *const this;
// const Maker*const this; 这是常函数修饰的
score = 200; // 4.mutable 修饰的成员变量在常函数中可以修改
cout << "score = " << score << endl;
}
public:
int id;
int age;
mutable int score; // mutable 修饰的成员变量
};
4. const修饰对象(常对象)
- 常对象只能调用const的成员函数
- 常对象可访问 const 或非 const 数据成员,不能修改,除非成员用mutable修饰
class Maker
{
public:
Maker(int id, int age)
{
this->id = id;
this->age = age;
score = 100;
}
void func()
{
cout << "普通成员函数 func() 调用" << endl;
}
void func2() const
{
cout << "常函数 func2() 调用" << endl;
}
public:
int id;
int age;
mutable int score;
};
// 常对象
void test()
{
Maker m1(1, 18);
m1.id = 100;
m1.func();
m1.func2(); // 普通对象也可以调用常函数
// 1.在数据类型前面加上const,让对象成为常对象
const Maker m2(1, 18);
// m2.id = 100;// 常对象不能修改普通成员变量
// m2.func(); // 常对象不能调用普通成员函数
m2.func2(); // 2.常对象可以调用常函数
cout << m2.age << endl; // 常对象可访问 const 或非 const 数据成员
m2.score = 200; // 3.常对象可以修改mutable修饰的成员变量
}
网友评论