1.成员变量和成员函数分开存储
在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才存放类的对象内存
class Person{
};
void test01(){
//空对象占有内存空间为1
/*C++编译器会给每个对象也分配一个字节空间,是为了区分空对象占内存中
的位置。*/
//每个空对象也应该有一个独一无二的内存地址
Person p;
cout <<"对象占内存"<<sizeof(p)<<endl;//输出为1
}
class Struend{
int m_A;//非静态的成员变量,存放在类的对象内存
static int m_B;//静态的成员变量,不存放类的对象内存
void func1(){};//非静态成员函数,不存放类的对象内存
static void func2(){};//静态成员函数,不存放类的对象内存
};
void test02(){
Struend stu;
cout <<"对象占内存"<<sizeof(stu)<<endl;//输出为4
//当在类中添加static int m_B;时
cout <<"对象占内存"<<sizeof(stu)<<endl;//输出为4
//当在类中添加 void func(){};时
cout <<"对象占内存"<<sizeof(stu)<<endl;//输出为4
//当在类中添加 static void func2(){};时
cout <<"对象占内存"<<sizeof(stu)<<endl;//输出为4
}
2.this指针概念
C++中的成员变量和成员函数是分开存储的,每一个非静态变量成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码。
那么问题是:这一块代码是如何区分那个对象调用自己呢?
C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属对象
当this所属的函数被p1调用,那么this这个指针就指向p1所属对象。
this指针的本质:是指针常量,指针常量的指向不可改变,指向的内容可以改变。
this的用途:
1.当形参和成员变量同名时,可以用this指针来区分
2.在类的非静态成员函数中返回对象本身,可使用 return *this
class Person{
public:
int Age;
Person(int Age){
this->Age = Age;
}
void PersonAddAge(Person &p){
this->age += p.age;
}
Person& PersonAddAge2(Person &p){
this->age += p.age;
return *this;
}
};
//当形参和成员变量同名时,可以用this指针来区分
void test01(){
Person p1(18);
cout << p1.Age<< endl;
}
//返回对象本身用*this
void test02(){
Person p1(12);
Person p2(18);
p2.PersonAddAge(p1)//输出是:30
/*如果要实现这种
p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
PersonAddAge()的返回值要是 Person& *this指向的是调用该函数对象本身
//PersonAddAge2的返回值是Person& Person的引用,所以一直是指向p2的
p2.PersonAddAge2(p1).PersonAddAge2(p1).PersonAddAge2(p1);
//输出是:44 这个也是链式编程
*/
//当返回值是Person时
p2.PersonAddAge2(p1).PersonAddAge2(p1).PersonAddAge2(p1);
//返回值是 30
//因为这时调用的拷贝函数创建的新对象,不是p2
}
3.空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针,如果用到this指针,需要加以判断保证代码健壮性。
class Person{
public:
int m_Age;
void showClassName(){
cout <<"this is Person class"<<endl;
}
void showPersonAge(){
//为了防止传来空指针,因此报错所以
if(this == NULL){
return;
}
cout <<"age = "<<this->m_Age<<endl;
}
};
void test01(){
Person *p;
p->showClassName();//可以调用
p->showPersonAge;
//不可以调用,this指向是一个空指针,没有对象无法访问到m_Age
}
4.const修饰成员函数
常函数:
1.成员函数后加const后称这个函数为常函数
2.常函数内不可以修改成员属性
3.成员属性声明时加关键字mutable后,在常函数中才可以修改。
常对象:
1.声明对象前加const称该对象为常对象
2.常对象只能调用常函数。
常函数
class Person{
public:
int m_A;
mutable int m_B;
void showPerson() const {
m_A = 100;//报错,常函数内不可以修改成员变量
//因为m_A = 100;是等价于 this->m_A = 100;
/*this指针的本质:是指针常量,指针常量的指向不可改变,
指向的内容可以改变。*/
/*当函数没有加const时,是指针常量const Person *const this;
当在函数上加const时就变成 const Person *const this;this这个指
针变成 常量指针常量 这样this指针的指向和内容都不可以改变。*/
m_B = 100;//可以修改,因为m_B上面加了关键字mutable
}
};
常对象
class Person{
public
int m_A;
mutable int m_B;
void showPerson() const{
}
void func(){
}
};
void main(){
const Person p;//在对象前加const,变为常对象
p.m_A = 100;//报错,因为常对象不可以修改属性
p.m_B = 100;//可以,因为加了关键字mutable
p.showPerson();//可以调用
p.func();//报错,常对象不可以调用普通函数,只能调用常函数
}