1 成员变量和成员函数分开存储
在C++中,类内的成员变量和成员函数分开存储。
只有非静态成员变量才属于类的对象:静态成员变量,静态、非静态成员函数都不属于类的对象
**空类创建的对象(空对象)所占的内存空间大小为1:**为了区分空对象占内存的位置,既每个空对象也应该有一个独一无二的内存地址。
#include <iostream>
#include <string>
using namespace std;
//成员变量和成员函数分开存储
class Person1
{
};
//空类创建的对象(空对象),占用的空间大小为1个字节:
//因为C++编译器给空对象分配一个字节的空间是为了区分空对象占内存的位置
//每个空对象也应该有一个独一无二的内存地址
void test01()
{
Person1 p;
cout << "空对象(空类的对象)占用的内存空间sizeof p=" << sizeof(p) << endl;
}
int main()
{
test01();
}
非静态成员变量:属于类的对象
静态成员变量:不属于类的对象
非静态成员函数:不属于类的对象
静态成员函数:不属于类的对象
#include <iostream>
#include <string>
using namespace std;
//成员变量和成员函数分开存储
class Person1
{
public:
int m_A;//非静态成员变量:属于类的对象
};
class Person2
{
public:
static int m_B;//非静态成员变量:不属于类的对象
};
class Person3
{
public:
void func() {}//非静态成员函数:不属于类的对象
};
class Person4
{
public:
void func() {}//静态成员函数:不属于类的对象
};
void test01()
{
Person1 p;
cout << "非静态成员变量:属于类的对象sizeof p=" << sizeof(p) << endl;//4
}
void test02()
{
Person2 p;
cout << "静态成员变量:不属于类的对象sizeof p=" << sizeof(p) << endl;//1
}
void test03()
{
Person3 p;
cout << "非静态成员函数:不属于某个对象sizeof p=" << sizeof(p) << endl;//1
}
void test04()
{
Person4 p;
cout << "静态成员函数:不属于某个对象sizeof p=" << sizeof(p) << endl;//1
}
int main()
{
test01();
test02();
test03();
test04();
}
2 this指针概念
C++中成员变量和成员函数是分开存储的。每个非静态成员函数也只会诞生一份函数实例,也就是说多个对象公用一块代码,那么问题是,这一块代码是如何区分哪个对象调用非静态成员函数呢?
C++通过提供特殊的对象指针,this指针,解决上述问题,this指针指向被调用的成员函数所属的对象。
(1)this指针是隐含每个非静态成员函数内的一种指针
(2)this指针不需要定义,直接使用即可
this指针的用途:
(1)当形参和成员变量同名时,可以用this指针来区分
(2)在类的非静态成员函数中返回对象本身,可使用return * this
#include <iostream>
#include <string>
using namespace std;
//this指针用途
//1.解决名称冲突
//2.返回对象本身用*this
class Person
{
public:
Person(int age)
{
//this指针指向,被调用的成员函数所属的对象,在本例中属于对象p
this->age = age;
}
Person personAddPerson(Person &p)
{
this->age += p.age;
//this为指向对象的指针,*this为对象本体
return *this;
}
int age;
};
//1.解决名称冲突
void test01()
{
Person p(18);
cout << "解决名称冲突:p的年龄为" << p.age << endl;
}
//2.返回对象本身*this
void test02()
{
Person p1(18);
Person p2(18);
p1.personAddPerson(p2).personAddPerson(p2).personAddPerson(p2);
//注意,如果personAddperson函数的参数为Person p(非引用),那么上述代码最终会返回36.
//因为是值传递,所以在调用的时候会调用拷贝构造函数,复制一个P1对象副本
cout << "p1的年龄为:" << p1.age << endl;
}
int main()
{
test01();
test02();
}
3 空指针访问成员函数
C++中空指针也是可以调用成员函数,但是也要注意有没有用到this指针
#include <iostream>
#include <string>
using namespace std;
//空指针调用成员函数
class Person
{
public:
void showClassname()
{
cout << "this is person class" << endl;
}
void showPersonage()
{
cout << "age=" <<age<< endl;
}
void showPersonage02()
{
if (this == NULL)
{
return;
}
cout << "age=" << age << endl;
}
int age;
};
//
void test01()
{
Person *p=NULL;
p->showClassname();//能成功运行
}
void test02()
{
Person* p = NULL;
p->showPersonage();
//不能成功运行,因为该函数调用了age属性,其实调用age等价于this->age
//但是由于该指针是一个空指针,没有指向一个确切对象,所以,不能访问对象的属性
}
void test03()
{
Person* p = NULL;
p->showPersonage02();
//成功运行
}
int main()
{
test01();
test02();
}
4 const修饰成员函数
常函数:
成员函数后加const后我们称这个函数为常函数
常函数内不可以修改成员属性,可以修改mutable修饰的成员属性
常对象:
声明对象前加const称该对象为常对象
常对象只能调用常函数,不能调用普通成员函数(因为普通成员函数可以修改成员属性)
常对象不能修改成员属性,但可以修改mutable修饰的成员属性
#include <iostream>
#include <string>
using namespace std;
//常函数
class Person
{
public:
//常函数:const修饰成员函数,其实修饰的是this指向,让指针指向的值也不可以修改
void showPersonage() const
{
//age=100;
//本句代码,等价于this->age=100;this指针的本质是指针常量,指针的指向是不可以修改的
m_B = 100;
}
int age;
mutable int m_B;//特殊变量:在常函数中也可以修改这个值
};
//1.常函数:不可以修改成员属性的值,但是如果成员属性前加mutable修饰,则可以进行修改
void test01()
{
Person p ;
p.showPersonage();
}
//2.常对象:
void test02()
{
const Person p ;//在对象前加const,变为常对象
//p.age = 100;//常对象不可以修改成员属性
p.m_B = 100;//常对象可以修改mutable修饰的属性
p.showPersonage();//常对象只能调用常函数
}
void test03()
{
Person* p = NULL;
//成功运行
}
int main()
{
test01();
test02();
}