如何写一个头文件?
255最近刚学了矩阵,因为矩阵实在是太难了,所以他照着老师课件上的计算方法一气之下写了个简陋的头文件,这样他就不用背那些复杂的知识点了
你将在本文看到的:
- 写一个头文件的思路
- 一个简陋的matrix.h头文件
如何开始?
如果想写一样东西,那么你就要构思这个东西是什么样的。比如说:
- 这个头文件都需要有什么功能?
- 怎么写这些功能?
- 如何写成一个模板?
- 如何使用写好的头文件?
这个头文件都需要什么功能?
为了想这一点,我先简单的写了一段代码:
#include <matrix.h>
using namespace std;
int main(){
Matrix<int> a, b;
a.read(); b.read();
a.print();
cout << endl;
b.print();
cout << endl;
Matrix<int> c,d,e;
c.matrix = a.matrix * b.matrix;
d.matrix = a.matrix + b.matrix;
e.matrix = a.matrix - b.matrix;
//为什么没有除呢?其实很简单,因为我不会(
c.print(); d.print(); e.print();
cout << endl;
c.transpose();
c.print();
return 0;
}
之后我们就可以一目了然的看出我们需要的功能了。
怎么写这些功能?
开始敲大致结构
首先,我们应该新建一个类,这样可以既可以使我们的思路保持清晰,而且类还有继承,封装,多态性,对象化等特性。对于一个类,大致长得像下面这样:
class ......{
public: ......
private: ......
protected: ......
}
- public,也就是公有成员,在类的外部是可以访问的
- private,也就是私有成员,在类的外部不可以访问
- protected,也就是受保护的成员,在类的子类是可以访问的
所以,我们应该在public内开数组及函数,大致写一下可得:
#include <bits/stdc++.h>
using namespace std;
class Matrix{
public:
vector< vector<int> > matrix;
void read(){
cin >> ln >> col;
for(register int i = 0; i < col; i++){
for(register int j = 0; j < ln; j++){
cin >> tmp;
swp.push_back(tmp);
}
matrix.push_back(swp);
swp.clear();
}
}
void print(){
for(register int i = 0; i < col; i++){
for(register int j = 0; j < ln; j++){
cout << matrix[i][j] << ' ';
}
cout << endl;
}
}
private:
int col=0, ln=0;
int tmp=0;
vector<int> swp;
}
再然后要写的,就只有一些函数和运算符重载了,函数具体可以访问这里
那么,如何重载运算符呢?
重载运算符
我们都知道,一个矩阵在代码里本质上就是一个二维数组,所以我们要重载的运算符类型也就很显然了。那么我们重载一个加法看看:
(矩阵加法运算过程)
vector< vector<int> > operator + (const vector< vector<int> > &a, const vector< vector<int> > &b){
vector< vector<int> > c;
if(a.size()==0||b.size()==0){ //特判0*0矩阵的情况,否则可能会出错
return c; //返回空矩阵
}
int lnA = a.size(); //A矩阵 - 行数
int colA = a[0].size(); //A矩阵 - 列数
int lnB = b.size(); //B矩阵 - 行数
int colB = b[0].size(); //B矩阵 - 列数
if (colA != colB||lnA != lnB){ //非两个m*n矩阵无法相加
return c; //返回空矩阵
}
c.resize(lnA); //调节行数
for (int i = 0; i < lnA; ++i) {
c[i].resize(lnB); //调节列数
}
for(register int i = 0; i < lnA; i++){
for(register int j = 0; j < lnA; j++){
c[i][j] = a[i][j] + b[i][j]; //相加
}
}
return c;
}
同理,我们也可以类比出减法的表示方式,只需要把+改为-即可
那么如何乘呢?
课件是这么说的:
设
所以可以写出代码如下:
vector< vector<int> > operator * (const vector< vector<int> > &a, const vector< vector<int> > &b){
vector< vector<int> > c;
if(a.size()==0||b.size()==0){//特判0*0矩阵
return c;
}
int lnA = a.size();
int colA = a[0].size();
int lnB = b.size();
int colB = b[0].size();
if (colA != lnB){//特判是否m*p p*n
return c;
}
c.resize(lnA);
for (int i = 0; i < lnA; ++i) {
c[i].resize(colB);
}
for (int i = 0; i < lnA; ++i){
for (int j = 0; j < colB; ++j){
for (int k = 0; k < colA; ++k){
c[i][j] += a[i][k] * b[k][j];//公式
}
}
}
return c;
}
到这里,我们已经写完了全部的功能!完结撒花(
如何写成一个模板?
我们的代码里好像有过这样的一段:
Matrix<int> a, b;
那么,尖括号可以由我们自己觉得是什么类型的matrix又是怎么做到的呢?
这时,就要用到我们的模板(template)大法了。
template <typename _(1)_ > _(2)_;
其中,(1)处要跟一个我们给这个任意的变量类型所起的名字,一般叫做T。(2)处要跟我们的函数
而这里,我们只需要在我们的Matrix类前加上template,如下:
template<typename T> class Matrix{ ....... };
然后,再把所有变量类型改为T即可(ln,col)除外。如:
vector< vector<T> > matrix;
......
这把就真的完结撒花了!文件请看这里
如何使用?
首先,将文件保存为.h(推荐)格式或其他,然后放入你的编译器include目录下。在我的电脑里,编译器include在这里:
C:\Program Files (x86)\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include
然后
#include <你的文件名.你保存的格式>
即可
测试程序