C++d对象与this指针
一、成员变量与成员函数分开存储。
在C++中,类内的成员变量和成员函数是分开储存的,只有非静态成员变量才属于类的对象上。
#include
using namespace std;
class Person{
public:
int m_A; //非静态成员变量 属于对象上
static int m_B; //静态成员变量 不属于对象上
void func() //非静态成员函数 不属于对象上
{
}
static void func2() //静态成员函数 不属于对象上
{
}
};
int main()
{
//Person p; //空对象占用内存空间为:1
//C++编译器都会给空对象分配1个字节的空间,是为了区分空对象占内存的位置。
//空对象在内存空间有一个独一无二的地址。
//cout << “sizeof(p):” << sizeof(p) << endl; //1
Person p;
cout << “sizeof(p):” << sizeof(p) << endl; //4
return 0;
}
二、this指针的概念。
通过第一点,我们知道在C++中成员变量和成员函数分开存储。
静态成员变量、静态成员函数都是在编译阶段已经分配好内存的了。
非静态成员函数是在运行代码之后,才会在代码去申请空间,由于函数在代码区申请的空间,只会诞生一份函数实例,也就是说,所以的同类型的对象都是公用这份代码。
那么问题来了: 这一块代码如何区分是哪个对象调用自己的?
C++通过提供特殊的对象指针:this指针,解决上述的问题,this指针指向被调用的成员函数所属的对象。
this指针是隐含在每一个非静态成员函数内的一种指针。
this指针不需要定义,直接使用就可以。
this指针的用途:
1)形参和成员变量同名时,可以用this指针加以区分。
2)在类的非静态成员函数中返回对象本身,可以使用return *this。
#include
using namespace std;
//this指针
/*
this指针的用途:
1)形参和成员变量同名时,可以用this指针加以区分。
2)在类的非静态成员函数中返回对象本身,可以使用return *this。
*/
class Person{
public:
Person(int age) //构造函数也是非静态的成员函数
{
//this指针指向被调用的成员函数所属的对象,其实就是this指向p1
//this->age代表访问这个对象p1的成员变量age
//谁调用这个有参构造,this就向谁。
this->age = age; //这时候this就是指向p1这个对象
}
//返回值这里写Person,那么返回的是p2的副本,并不是p2的本身,所以后续累加都是对副本进行操作,p2没有动过。
//返回值这里写Person&,那么返回的是p2的本身,所以后续的累加是对p2的本身作累加。
Person& PersonAddAge(Person &p)
{
this->age += p.age;
return *this;
}
int age;
};
int main()
{
//1. 使用this指针来解决名字冲突
//Person p1(18);
//cout << “p1的年龄:” << p1.age << endl;
//Person p2(28);
//cout << “p2的年龄:” << p2.age << endl;
//2. 返回对象本身用*this。
Person p1(10);
Person p2(10);
//p2.PersonAddAge(p1);
//cout << “p2的年龄:” << p2.age << endl;
//C++链式编程思想
p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
cout << “p2的年龄:” << p2.age << endl;
return 0;
}
三、空指针访问成员函数。
C++空指针也是可以调用成员函数的,但是要注意有没有使用到this指针。
如果用到了this指针,需要加以判断保证代码的健壮性。
#include
using namespace std;
//空指针调用成员函数
class Person{
public:
void showClassName() //该非静态成员函数没有使用到this指针
{
cout << “this is Person class!” << endl;
}
void showPersonAge()
{
if(this == NULL)
{
return;
}
//其实在这里,每一个成员变量默认都是使用this指针指向的。
//也就是说,这里的m_Age,其实就是this->m_Age;
//因为我们没有创建对象,所以this没有指向确切的实体。
//所以this是NULL,因为是NULL,并且还在访问成员,所以就段错误。
cout << “age = “ << m_Age << endl;
}
int m_Age;
};
int main()
{
Person *p = NULL;
p->showClassName();
p->showPersonAge();
return 0;
}
四、const修饰成员函数。
常函数:
成员函数后加const后,我们称这个函数为常函数。
常函数内不可以修改成员属性。
成员属性声明时加关键字mutable后,在常函数中依然可以修改。
常对象:
声明对象前加const称该对象为常对象。
常对象只能调用常函数。
#include
using namespace std;
//常函数
/*
成员函数后加const后,我们称这个函数为常函数。
常函数内不可以修改成员属性。
成员属性声明时加关键字mutable后,在常函数中依然可以修改。
*/
/*
常对象:
声明对象前加const称该对象为常对象。
常对象只能调用常函数。
*/
class Person{
public:
Person(int a)
{
this->m_A = a;
}
void showPerson() const //常函数
{
//m_A = 100; //在常函数中修改成员属性。
m_B = 100;
}
void func() //普通函数
{
}
int m_A; //普通变量,不是一个常量
mutable int m_B; //特殊变量,即使在常函数中,也可以修改这个值 (加了mutable,从”常”变成”不常”)
};
int main()
{
/*
Person p; //普通对象 : 可以调用普通函数,也可以调用常函数
p.showPerson();
p.func();
*/
const Person p(100);
//p.m_A = 100; //错误
p.m_B = 100;
p.showPerson();
//p.func(); //p是常对象,所以只能调用常函数,不能调用普通函数。
return 0;
}
总结:
1)在函数头后面加const,这个函数就是常函数。
2)如果类中有普通变量,则在常函数中不能修改这个普通变量。
3)如果类中有普通变量,但是这个普通变量在声明前加了一个mutable,那么这个变量就变成特殊变量。
4)在常函数中可以修改特殊变量的值。
5)在声明对象前加一个const,这个对象就变成常对象。
6)声明了常对象,也就意味着这个类中普通变量都是常的,所以构造函数去给普通变量赋值。
不能先声明常对象,然后在常对象后面再给普通变量中,因为声明常对象,普通变量由于是常的,没有值,就会报错。
7)常对象可以修改mutable修饰的变量。
8)常对象只能调用常函数,不能调用普通函数。
还没有评论,来说两句吧...