this指针
this指针是一个系统预定义的特殊指针,存的是对象自己的地址,指向对象自己。
例如:
p1.disp();
被转化为
p1.disp(&p1);
class Point
{
int x,y;
public:
Point(int x,int y)
{
this->x=x; // = 左边是数据成员,右边是形参
this->y=y;
}
};
-
this指针存储的是对象自己的地址
-
系统利用this指针明确指出成员函数当前操作的对象
-
当对象调用成员函数时,编译器先将该对象的地址赋给this指针,然后调用成员函数,隐含使用了this指针
-
类成员函数的真正原型是:
函数返回类型 函数名称(类名*this,其他参数) -
编译器为支持this指针必须应用两个转变
-
(1)改变类成员函数的定义,用额外参数this指针来定义每个成员函数
-
(2)改变每个类成员函数的调用加上一个额外的实参–被调用对象的地址
对象数组
对象指针数组
一维对象数组格式
类名 数组名【下标表达式】;
Person student[10];
使用对象数组时,只能访问单个元素
数组名【下标】. 成员名
#include<iostream>
#include<string>
using namespace std;
class Teacher
{
int workId;
string name;
int age;
string researchArea;
public:
Teacher(int wordId = 0, string na = "noname", int age = 0, string resArea = "")
{
this->workId = workId;
this->name = na;
this->age = age;
this->researchArea = resArea;
}
void disp()
{
cout << workId << "\t" << name << "\t" << age << "\t" << researchArea << endl;
}
void setTeacher(int wordId = 0, string na = "noname", int age = 0, string resArea = "")
{
this->workId = workId;
this->name = na;
this->age = age;
this->researchArea = resArea;
}
};
int main()
{
Teacher teacherGroup[3];
int workId;
string name;
int age;
string resArea;
for (int i = 0; i < 3; i++)
{
cout << "输入教师信息:\n" << "编号\t姓名\t年龄\t研究领域\n";
cin >> workId;
cin >> name >> age >> resArea;
teacherGroup[i].setTeacher(workId, name, age, resArea);
}
for (int i = 0; i < 3; i++)
teacherGroup[i].disp();
Teacher*pTeacherGroup[3];
//对象是每个teacher类元素的地址
for (int i = 0; i < 3; i++)
{
pTeacherGroup[i] = &teacherGroup[i];
}
cout << "使用指针输出教学团队中的各个成员的值" << endl;
for (int i = 0; i < 3; i++)
{
pTeacherGroup[i]->disp();
}
return 0;
}
类的组合
当一个类的对象作为另一个类的成员时,这两个类之间的关系就称为组合关系。
Circle称为组合类,Point类对象称为嵌入对象
组合类构造函数一般形式:
类名::类名(形参列表) : 嵌入对象名1(实参列表),嵌入对象名2(实参列表),…
{
//基类类型数据成员的初始化
}组合类的复制构造函数的一般定义形式是:
类名::类名(类名&对象名) : 嵌入对象名1(实参列表),嵌入对象名2(实参列表),…
{
//基类类型数据成员的初始化
}
在创建类的组合对象时,不仅会调用组合类的构造函数,也会调用嵌入对象的构造函数
对象的动态初始化
类对象的动态初始化,使得对象的初始值可在运行时被指定,可以重载构造函数,提供各种初始化的形式
类的静态成员
对于非静态数据成员,每个类对象都有自己的副本,而静态数据成员对象对每个类类型只有一个副本
使用静态数据成员的优势:
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性
- 可以实现信息隐藏,静态数据成员可以是private成员,而全局对象不能
静态数据成员的初始化在类体外(文件作用域内),前面不加static
静态数据成员初始化格式:
<类型> <类名> :: <静态数据成员> = <值>;
在引用静态数据成员时格式:
<类型> ::<静态数据成员> 或
<对象名> . <静态数据成员>
#include<iostream>
#include<string>
using namespace std;
class Student
{
string name;
float score;
public:
static int studentCount; //定义静态数据成员,学生人数计算器
Student(string na = "noname", float sc = 0) //构造函数定义
{
studentCount++; //每调用一次构造函数,计数器加一
name = na;
score = sc;
}
Student(const Student&s) //拷贝构造函数定义
{
studentCount++; 每调用一次复制构造函数,计数器加一
name = s.name;
score = s.score;
}
~Student() //析构函数的定义
{
studentCount--; //每调用一次析构函数,计数器减一
}
void disp()
{
cout << name << "\t" << score << endl;
}
};
int Student::studentCount = 0; //初始化Student的静态数据成员
int main()
{
Student haha("哈哈", 18);
//studentCount变为 1
cout << "学生数=" << haha.studentCount << "\n" << endl; //显示静态数据成员的值
Student haha_copy(haha);
//调用拷贝构造函数初始化,执行++,静态数据成员studentCount变为2
cout << "学生数=" << haha.studentCount << "\n" << endl; //显示静态数据成员的值
Student classOne[10];
//定义含有10个student类对象的数组,每个对象的创建调用构造函数初始化,调用++,静态数据成员studentCount变为12
cout << "\n" << Student::studentCount;
//通过类访问类的静态数据成员
Student *pS = new Student[10];
//动态创建10个对象,每个对象的创建调用构造函数初始化,执行++,静态数据成员变为 22
cout << "\n" << haha.studentCount<<"\n"<<endl;
delete[]pS;
//释放动态创建的这10个对象构成的数组,每个对象数据成员的释放调用student类的析构函数,执行--,变为12
cout << "学生数=" << haha.studentCount << "\n" << endl;
return 0;
}
静态成员函数
静态成员函数与静态数据成员一样,从属于类,加static
调用静态成员函数格式:
<类名> :: <静态成员函数> (参数表)
或
<对象> . <静态成员函数> (参数表)
静态成员函数只能访问静态数据成员,静态成员函数和类以外的函数和数据,不能访问类中的非静态数据成员
静态成员函数没有this指针,因此,静态成员函数只能访问类中的静态成员