37 类的静态成员
https://www.cctry.com/thread-290010-1-1.html
例如:Student类,加一个变量:校长master。如果定义为普通的成员变量,每个对象都要开个内存放master,而且如果换一个校长了,每个对象的master都要一个个修改。
这时可以定义为静态成员,在前面加static
,这样这个成员就是属于类的而不是属于某个对象的(类似全局变量,但作用域是在整个类当中)
①、这样所有对象都可以直接访问这个静态成员变量,而且值是一样的;
②、静态成员变量在内存中只占用一份存储空间;
③、静态成员变量的值对于所有对象来说都是一样的。如果其中一个对象调用函数将其改变了,那么其他成员在访问这个静态成员变量的时候的值都是改变之后的;
④、只要在类中定义了类的静态成员变量,那么就占用存储空间了,不管有没有定义这个类的对象,因为静态成员变量不属于任何类对象,而是属于该类;
⑤、静态数据成员需要在类外进行声明或声明并初始化,否则在使用的时候会报链接的错误;例:int CStudent::master = 0;
⑥、类的静态成员在定义的时候需要加 static,在类外声明的时候不需要加 static 关键字;
⑦、不能用构造函数的参数初始化表的形式对静态成员进行初始化操作;
⑧、静态数据成员既可以通过对象名引用,也可以通过类名来直接引用,(一般都用类名引用,用以和普通成员区分开)CStudent::master
⑨、public 公有类型的静态数据成员,可以被类的对象引用,也可以直接用类名来引用。但如果静态数据成员被定义成private私有的,那么通过对象或者类名来引用都是不可以的,必须通过类的public类型的静态成员函数来引用了。
38 运算符重载
https://www.cctry.com/thread-290018-1-1.html
例:
之前在用对象赋值那里提到的,会让两个指针指向同一块内存的情况,可以重载等号=
CStudent& CStudent::operator=(const CStudent& stud) //"operator="是函数名
//operator这个关键字不能变,后面跟着什么运算符就是重载什么运算符
//原来是stud2 = stud1; 在这里,相当于stud2是本对象,stud1是目标对象(参数的那个stud)
{
if (p_name)
{
delete[] p_name;
p_name = NULL;
}
int name_len = strlen(stud.p_name) + 1;
p_name = new char[name_len];
memset(p_name, 0, name_len);
strcpy(p_name, stud.p_name);
sex = stud.sex;
num = stud.num;
age = stud.age;
return *this;
}
重载运算符的规则:
①、C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载:
例如,在VB中可能有的人会使用运算符,例如:35,表示3的5次方,如果你想在C++中创建**运算符并实现重载,那是不行的。②、C++允许与不允许重载的运算符如下图:
③、重载运算符不能改变运算符操作对象的个数:例如 > 和 < 运算符,本身是比较用的双目运算符,也就是说要有2个操作数,如果你重载完了之后变成不是2了,那肯定不行;
④、重载运算符不能改变运算符的优先级别,乘除 */ 运算符的优先级别大于±,如果你重载完了之后导致优先级改变了,那肯定也不行;
⑤、重载运算符不能改变运算符的结合性,例如,赋值运算符=是从右向左开始结合的,如果你重载完了之后导致从左往右了,那肯定也不行;
⑥、重载运算符的函数不能有默认的参数:不然就改变了运算符参数的个数,与第③点矛盾了;
⑦、重载运算符的函数参数至少有一个是本类的对象或引用,不能全部都是C++的基本类型,例如:CStudent& CStudent::operator+(int a, int b)
这种也是不行的;
⑧、重载运算符应该遵循运算符原有的含义,不能把+重载之后变成-的功能,虽然语法上没有错误,但是违背了重载运算符的初衷!
小作业:
为 CStudent 类重载 ==运算符,判断两个 CStudent 对象是否相等,或者说是否是同一个学生的数据。
#include <iostream>
#include <string>
using namespace std;
class CStudent
{
public:
char* p_name;
char sex;
int num;
int age;
public:
CStudent()
{
p_name = NULL;
}
CStudent(const char* t_name, char t_sex, int t_num, int t_age);
CStudent& operator=(const CStudent& stud);
bool operator==(const CStudent& stud);
~CStudent();
};
CStudent::CStudent(const char* t_name, char t_sex, int t_num, int t_age) :sex(t_sex), num(t_num), age(t_age)
{
int n_len = strlen(t_name) + 1;
p_name = new char[n_len];
memset(p_name, 0, n_len);
strcpy_s(p_name, n_len, t_name);
}
CStudent& CStudent::operator=(const CStudent& stud)
{
sex = stud.sex;
num = stud.num;
age = stud.age;
if (p_name)
{
delete[] p_name;
p_name = NULL;
}
int name_len = strlen(stud.p_name) + 1;
p_name = new char[name_len];
memset(p_name, 0, name_len); //初始化函数。作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
strcpy_s(p_name, name_len, stud.p_name);
return *this;
}
bool CStudent::operator==(const CStudent& stud)
{
int flag = 1;
if (*p_name != *stud.p_name)
{
flag = 0;
}
if (sex != stud.sex)
{
flag = 0;
}
if (num != stud.num)
{
flag = 0;
}
if (age != stud.age)
{
flag = 0;
}
if (flag == 1)
{
return true;
}
if (flag == 0)
{
return false;
}
}
CStudent::~CStudent()
{
if (p_name)
{
delete[] p_name;
p_name = NULL;
}
cout << "CStudent::~CStudent()" << endl;
}
void test()
{
CStudent stud_1("zhangsan", 'f', 1001, 20),stud_2;
stud_2 = stud_1;
if (stud_1 == stud_2)
{
cout << "是同一个学生" << endl;
}
else
{
cout << "不是同一个学生" << endl;
}
}
int main()
{
test();
return 0;
}