三:C++函数
前文
本章较详细内容为类的预先部分,更新函数是一个不错的选择。
正文
函数的基本概念
1
2
3
returnType funcName(params) {
// ToDo
}
如上,基本的函数构成由返回类型、函数名、参数、函数体构成,main
就是一个函数, 注意到,returnType并不是必须的,但这不意味着不需要写,不返回一个东西时应写void
, 其次在有返回类型时,函数体的最后一行应写return your_var
,有且只有main
函数返回类型是int
但 不需要写return 0
,因为C++默认返回0
,其次函数的参数需要带类型,如int a, int &a, int *a
,左边 三个例子中依次传入了正常的变量,变量的引用,变量的地址。
函数声明和调用
函数声明目的是告诉编译器有一个这样的函数,但定义可能在其他地方。
1
2
returnType funcName(params);
调用函数即funcName(your params);
,这里your params
不需要数据的类型,如funcName(10, 20, &a, *b)
。
值得注意的是,并不是什么代码都分解成一个个函数比较好,这是因为调用函数时,程序的控制权会交给函数, 这意味着会有不断的内存跳跃,性能会有影响,不过大多数时候把共同部分拿出来都是使代码易读较好的选择。
参数的默认值
定义一个函数时可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空, 则使用这个默认值,如:
1
2
int sum(int a, int b=20);
// sum(a) 这里不传入b的值,默认为20
函数的重载
重载指参数列表和定义(实现)不相同,函数名相同。 如在一个类中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class printData
{
public:
void print(int i) {
cout << "整数为: " << i << endl;
}
void print(double f) {
cout << "浮点数为: " << f << endl;
}
};
int main(void)
{
printData pd;
// 输出整数
pd.print(5);
// 输出浮点数
pd.print(500.263);
return 0;
}
这并不意味着引用和指针都能作为不同的参数,如:
1
2
3
4
5
6
7
8
9
void plusOne(int &a) {
a++;
}
void plusOne(int a) {
a++;
}
void plusOne(int *a) {
(*a)++;
}
当试图编译上述代码,会报:error: call of overloaded ‘plusOne(int&)’ is ambiguous
,因为对于调用来说, 引用和普通变量都是int b = 10; plusOne(b);
,plusOne(int *a)
没关系,因为int *a
是一个明确的指针变量, 对应的调用是plusOne(&b)
。
同样的,运算符也可以重载(大部分运算符是可以重载的,少部分如.,::,->
等不行),例如<<
是移位运算符,但是iostream
能够输出字符串等,这是因为<<
被重载了所以能适应不同数据类型的输入输出,具体在iostream
引入的ostream
中,部分代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace std {
template<class CharT, class Traits = char_traits<CharT>>
class basic_ostream : virtual public basic_ios<CharT, Traits> {
public:
...
// formatted output
basic_ostream& operator<<(basic_ostream& (*pf)(basic_ostream&));
...
basic_ostream& operator<<(bool n);
...
basic_ostream& operator<<(const void* p);
...
}
}
其中还有熟悉的操作符定义:
1
2
endl // outputs '\n' and flushes the output stream
ends // outputs '\0'