- A compound statement may be needed to execute many times
- You can copy them several times, but you can use functions
```cpp
include
include
struct Matrix { int rows; int cols; float *pData; };
int main() { using namespace std;
Matrix matA = {3, 4};
matA.pData = new float[matA.rows * matA.cols]{1.f, 2.f, 3.f};
Matrix matB = {4, 8};
matB.pData = new float[matB.rows * matB.cols]{10.f, 20.f, 30.f};
Matrix matC = {4, 2};
matC.pData = new float[matC.rows * matC.cols]{100.f, 200.f, 300.f};
// some operations on the matrices
float maxa = FLT_MIN;
float maxb = FLT_MIN;
float maxc = FLT_MIN;
//find max value of matA
for (int r = 0; r < matA.rows; r++)
for (int c = 0; c < matA.cols; c++)
{
float val = matA.pData[r * matA.cols + c];
maxa = (maxa > val ? maxa : val);
}
//find max value of matB
for (int r = 0; r < matB.rows; r++)
for (int c = 0; c < matB.cols; c++)
{
float val = matB.pData[r * matB.cols + c];
maxb = (maxb > val ? maxb : val);
}
//find max value of matC
for (int r = 0; r < matC.rows; r++)
for (int c = 0; c < matC.cols; c++)
{
float val = matC.pData[r * matC.cols + c];
maxc = (maxc > val ? maxc : val);
}
cout << "max(matA) = " << maxa << endl;
cout << "max(matB) = " << maxb << endl;
cout << "max(matC) = " << maxc << endl;
delete[] matA.pData;
delete[] matB.pData;
delete[] matC.pData;
return 0;
}
// result // max(matA) = 3 // max(matB) = 30 // max(matC) = 300
上面代码中,构建了三个结构体实例,找出每个结构体中最小的元素,那么不使用函数的话,会依次对三个结构体的`pData`进行遍历比较,得到结果,相似的运算会重复执行三遍。
So, We can put the compound statement into a function.
```cpp
#include <iostream>
#include <float.h>
struct Matrix
{
int rows;
int cols;
float *pData;
};
float matrix_max(struct Matrix mat)
{
float max = FLT_MIN;
//find max value of mat
for (int r = 0; r < mat.rows; r++)
for (int c = 0; c < mat.cols; c++)
{
float val = mat.pData[r * mat.cols + c];
max = (max > val ? max : val);
}
return max;
}
Matrix *create_matrix(int rows, int cols)
{
Matrix *p = new Matrix{rows, cols};
p->pData = new float[p->rows * p->cols]{1.f, 2.f, 3.f};
//you should check if the memory is allocated successfully
return p;
}
bool matrix_add(const Matrix &matA, const Matrix &matB, Matrix &matC)
{
// check the dimensions of the three matrices
// re-create matC if needed
// do: matC = matA + matB
// return true if everything is right
return true;
}
int main()
{
using namespace std;
Matrix matA = {3, 4};
matA.pData = new float[matA.rows * matA.cols]{1.f, 2.f, 3.f};
Matrix matB = {4, 8};
matB.pData = new float[matB.rows * matB.cols]{10.f, 20.f, 30.f};
Matrix matC = {4, 2};
matC.pData = new float[matC.rows * matC.cols]{100.f, 200.f, 300.f};
// some operations on the matrices
float maxa = matrix_max(matA);
float maxb = matrix_max(matB);
float maxc = matrix_max(matC);
cout << "max(matA) = " << maxa << endl;
cout << "max(matB) = " << maxb << endl;
cout << "max(matC) = " << maxc << endl;
delete[] matA.pData;
delete[] matB.pData;
delete[] matC.pData;
return 0;
}
- If
Matrix::pData
is NULL or an invalid value, how to tell the calling function from the called one?- The pointer should be checked first!
- 函数一开始,需要对数据进行一系列严谨的检查
函数在程序中的位置
- 函数必须在其被调用之前定义
- 或者先声明,然后函数的调用和实现的顺序就没关系了。声明的时候需要返回类型,函数名字,参数列表,参数列表中要有每个参数的数据类型 ```cpp // draw.cpp // The function must be defined before it was called
bool drawLine(int x1, int y1, int x2, int y2) { // Source code here return true; }
bool drawRectangle(int x1, int y1, int x2, int y2) { // some calculation here drawLine(…); drawLine(…); drawLine(…); drawLine(…);
return true;
}
更加清晰的代码组织结构<br />我们会将同一类的函数放在同一个`.cpp`文件中,这个文件中的所有函数需要有**声明,声明会统一放到头文件中,在头文件中,还需要写宏定义。**
```cpp
#ifndef __DRAW_H__
#define __DRAW_H__
...
#endif
如果调用了两遍#include <draw.h>
头文件时,这时候函数的声明就会出现两次,编译就会出错。所以宏定义的功能:如果已经调用了一次头文件,第二次调用的时候就会为空,相当与没有include
。
// draw.h
#ifndef __DRAW_H__
#define __DRAW_H__
bool drawLine(int x1, int y1, int x2, int y2);
bool drawRectangle(int x1, int y1, int x2, int y2);
#endif
// draw.cpp
#include <draw.h>
bool drawRectangle(int x1, int y1, int x2, int y2)
{
// some calculation here
drawLine(...);
drawLine(...);
drawLine(...);
drawLine(...);
return true;
}
// define it later
bool drawLine(int x1, int y1, int x2, int y2)
{
// Source code here
return true;
}
// main.cpp
#include <draw.h>
int main()
{
// ...
drawRectangle(10, 20, 50, 100);
// ...
}
How are functions called?
- A call stack can store information about the active functions of a program
- Store the address the program returns after the function call
- Store the registers
- Store the local variables
- // do some work of the called function
- Restore the registers
- Restore the local variables
- Store the function returned result
- Jump to the return address
The cost to call a function!