前言
这一章主要教如何写一个Class。首先我们要知道什么是Class(类),我觉得之前用的vector,list和deque这样的容器就是一种Class,这样的容器有一个共通操作,比如vector_.size(),这样的共通操作可以极大降低我们的代码量。但这样的容器也有一定的局限,比如vector只能放一类数据等。 Class的一定格式为
class my_class{
public:
private:
int _size;
};
这里可以写变量,函数等等,在调用的时候使用“.”运算符,比如如下代码
my_class ClassA;
ClassA._size;
可以查询一个数据类型为my_class,结构体名为ClassA的size。(class可以看作是C语言里的结构体。)
一、构造函数及读取/写入
??回想一下我们使用vector、数组的时候,我们首先是要赋值,赋值的方式也是多种的,有默认空值、指定数量的空值、指定数量的定值等等。在Class中称为构造函数。构造函数也是函数,函数的名字必须与Class名一样,是用来初始化对象的一类函数。 常见的方法有以下几种
class my_class{
public:
my_class();
my_class(string &,int num ,int Chinese,int Math);
private:
int _Chinese,_Math,_num;
string _name;
};
??注意上述代码只是进行了声明,还需要对构造函数进行定义,如代码中的语句1没有提供任何信息,因此我们需要提供一些默认的值,之后还是可以修改的;而语句2提供了一些参数,因此可以直接赋值。如以下代码
my_class::my_class()
{_name="xiaoming";_num=0;_Chinese=0;_Math=0;}
my_class::my_class(string &name,int num ,int Chinese,int Math)
{_name=name;_num=num ;_Chinese=Chinese;_Math=Math;}
在定义的时候需要注意一下关键词
my_class::
该关键词指定了类,多个类就需要多个构造函数,因此为了进行区分,必须指明是哪个类的构造函数。 声明、定义完成后就可以调用了
my_class student1;
string t1 = "xiaoai";my_class student2(t1, 01, 80, 90);
??上面我们就初始化了两个变量,如果我们想查询这两个变量的信息,我们会首先想到一下错误的引用方法:
cout<<student1._name<<student1._num<<student1._Chinese<<student1._Math;
cout<<student2._name<<student2._num<<student2._Chinese<<student2._Math;
错误的地方在于,class中我们把这几个信息放在了private ,因此无法这样查询,这能防止不小心改了一些重要的值,如果想改写、读取可以通过函数的方式读取,比如
class my_class{
public:
string read_name(){return _name;}
void write_name(string & new_name){_name=new_name;}
private:
int _Chinese,_Math,_num;
string _name;
};
这样我们就可以通过"."操作读取/改写一定的值了,比如:
cout<<student2.read_name();
string name2="xiaoming";
student2.write_name(name2;)
二、运算符重载
我们定义了一个Class之后,可能会需要一定的运算关系,比如矩阵的加法、乘法、点乘等等操作,但是这些操作是不会“自适应”变化的,即二维数组*二维数组不会是矩阵的运算方法,因此需要对这些运算符进行重载。以一个矩阵的class的点乘和矩阵乘法为例
class Matrix{
public
Matrix operator*(const Matrix&,const Matrix&);
Matrix operator**(const Matrix&,const Matrix&);
};
声明中operator 后面接想重载的运算符,然后括号里接收需要的数据。之后定义好重载符后,即可以实现相对应的运算方式
Matrix operator*(const Matrix& _left, const Matrix& _right)
{
}
int main(){
Matrix m1,m2;
cout << m1 * m2;
cout << m2 * m1;
}
有时候我们想直接使用这样的语句读取整个对象:cout<<m1; 然而这样是不行的,因此还有一种常用的符号需要重载:<<。
Matrix operator<<(const Matrix& _m)
{
for(int ix=0;ix<rows();ix++)
for (int iy = 0; iy < column(); iy++)
{
cout << _matrix[ix][iy];
if (iy == 3) os << endl;
else os << " ,";
}
}
三、一般class的要素
class 类名(){
public:
1.构造函数
2.读取private的函数
3.写入private的函数
private:
必要的数据
};
类名::函数名1(参数表1){实现代码;}
类名::函数名2(参数表2){实现代码;}
类名 变量名1;
类名 变量名2;
四、function object
记得第三章的习题有一个自己写function object,其实现的方法其实也是class,其实最重要的一步就是重载了运算符() 考虑一个less_than函数,在class内存储了一个基准值,将传入的参数与基准值对比,返回一个boll值。
class less_than{
public:
less_than(int value){_val=value;}
bool operator()(int _value){return _value<_val;}
private:
int _val;
};
这里对()进行了重载,当我们定义了一个less_than 类型的时候,如
less_than lt50(50);//这里是构造
那么50就绑定到了lt50为变量名的class中的_val,注意这里没有进行对比,这里是调用了构造函数。对比的时候调用
lt50(30);//这里是调用
这样就调用了重载的()
通常我们会把function object当作参数传给泛型算法。
|