静态成员
静态成员变量:
所有对象共享同一份数据,在编译阶段分配内存(全局区),类内声明,类外初始化,也有访问权限。
class Person
{
public:
static int P_a;//类内声明
};
int Person::P_a = 100;//类外初始化
共享数据:
void test()
{
Person p1;
cout << "p1.P_a=" << p1.P_a << endl;
Person p2;
p2.P_a = 200;
cout << "p1.P_a=" << p1.P_a << endl;
}
int main()
{
test();
system("pause");
}
上述访问静态成员变量是采用通过对象进行访问
也可以通类名进行访问:
cout << "P_a=" << Person::P_a << endl;
代码运行前:代码区、全局区,代码运行后:堆区、栈区
静态成员函数:
所有对象共享同一个函数,静态成员函数只能访问静态成员变量吗,同上也有两种访问方式:对象、类名,也有访问权限。
class Person
{
public:
static int P_a;//类内声明
int P_b;
static void func()
{
P_a = 0;//静态成员函数可以访问静态成员变量
//P_b = 0;//不可以访问非静态成员变量,编译器无法确定是哪个对象的P_b
cout << "静态成员函数" << endl;
}
};
void test2()
{
Person p1;
p1.func();//通过对象进行访问
Person::func();//通过类名进行访问
}
this指针知识:
只有非静态成员变量属于类的对象,静态成员变量,成员函数,静态成员函数均不属于类的对象。空对象占用内存空间为1,是为了区分空对象占内存的位置,每个空对象也应该有自己独有的内存地址。
就非静态成员函数而言,只有一个,怎么分配给多个对象呢,通过this指针,this指针是隐含每一个非静态成员函数内的一种指针,不需要定义直接使用即可。
this指针作用
1、解决名称冲突
#include <iostream>
#include<string>
using namespace std;
class Person
{
public:
int age;
Person(int age) //如果构造函数的形参和成员变量名称一致时就会出现错误,导致没有传入任何参数。
{
age = age;
}
};
void test()
{
Person p1(18);
cout << "p1的年龄:" << p1.age << endl;
}
int main()
{
test();
system("pause");
}
解决方法:
(1)使用不同的名称,规范名称
class Person
{
public:
int m_age;
Person(int age)
{
m_age = age;
}
};
(2)使用this指针
class Person
{
public:
int age;
Person(int age)
{
this->age = age;//this指针指向被调用的成员函数所属的对象
}
};
2、返回对象本身用*this
class Person
{
public:
int age;
Person(int age)
{
this->age = age;
}
void add(const Person& a)
{
this->age = this->age + a.age;
}
};
void test()
{
Person p1(18);
cout << "p1的年龄:" << p1.age<< endl;
Person p2(2);
cout << "p2的年龄:" << p2.age << endl;
p2.add(p1);
cout << "p2的年龄:" << p2.age << endl;
}
需求:要求p2的年龄加上p1的年龄多次,不能直接这样写:
p2.add(p1).add(p1).add(p1).add(p1);
因为只有当add()这个函数返回值是p2时才能像这么写
class Person
{
public:
int age;
Person(int age)
{
this->age = age;
}
Person & add(const Person& a) //引用是地址传递
{
this->age = this->age + a.age;
return *this;//this是指向p2的指针,而*this指向的就是p2这个对象本身
}
};
void test()
{
Person p1(18);
cout << "p1的年龄:" << p1.age<< endl;
Person p2(2);
cout << "p2的年龄:" << p2.age << endl;
p2.add(p1).add(p1).add(p1).add(p1);//链式编程思想
cout << "p2的年龄:" << p2.age << endl;
}
如果不采用引用方式,而采用值方式返回
Person add(const Person& a) //引用是地址传递
{
this->age = this->age + a.age;
return *this;//this是指向p2的指针,而*this指向的就是p2这个对象本身
}
因为之前构造函数部分讲过,以值方式返回局部对象会调用拷贝构造函数,会创建一个新的对象,新的对象的age会变化,但p2这个对象的age只会加一次。
当空指针访问成员函数
class person
{
public:
int m_age;
void showage()
{
cout << "age=" << m_age << endl;//当调用属性时,默认是
//cout<<"age="<<this->m_age<<endl;this自动会调用
}
};
void test1()
{
person* p = NULL;//但当定义空指针时,this没有指向一个确切的对象,是空,this->m_age就会错
p->showage();
}
为了系统不崩溃,可以:
class person
{
public:
int m_age;
void showage()
{
if(this == NULL)
{
return;
}
cout << "age=" << m_age << endl;
}
};
const修饰成员函数
class person
{
public:
int m_age;
mutable int b;
void showage1()
{
m_age=100;//等价于this->m_age=100; this指针的本质是指针常量,指针的
//指向是不可以修改的
}
//若同时不想修改成员变量的值
void showage2()const//在成员函数后面加const,修饰的是this指针,让指针指向的值也不可以修改
{
//在这种函数中一般的变量不允许修改
//特殊的:mutable关键字修饰的变量
b = 2;
}
};
void test2()
{
const person p;//常对象,在对象前加const,变为常对象
//属性不允许修改,除了mutable修饰的属性
//常对象只允许调用常函数
}