1.函数的缺省参数:
函数在函数头中可以指定形参的值,这种方式称为缺省参数,在用户不输入该参数时采用默认值,形式如下:
返回数据类型 函数名(参数类型 参数1,参数类型 参数2=默认值);
注意
-
在函数中有多个参数时,传递参数会按照位置依次传递,编译器无法识别到底哪个是用的缺省参数还是传递的参数。代码示例:
int foo(int a=1, int b=10, char* str = "hello!")
{
cout << "a = " << a << ", b = " << b << ", str = " << str << endl;
}
foo(3,"hello"); //错误使用,函数传递的值默认第二个参数传递的是b的值而不是c的值
foo(3);
foo("hello");
结果:
2.函数的值传递
实参在传递进函数时会生成一个该类型的默认对象,函数中的所有操作都是对这个构建的默认对象的操作而不是对实参本身的操作。除非调用指针。
代码示例:
#include <iostream>
using namespace std;
void foo(int a, int b)
{
a = 10;
b = 20;
}
void foo(int * ap, int* bp)
{
int* tem;
ap = bp;
bp = tem;
}
//使用指针类型的形参,在函数中通过指针操作函数
void fun(int* pa, int* pb)
{
*pa = 10;
*pb = 20;
}
void swap(int* pa, int* pb)
{
int tem = *pa;
*pa = *pb;
*pb = tem;
}
//使用引用类型的形参
void swap(int& a, int& b)
{
int tem = a;
a = b;
b = a;
}
int main()
{
int a = 1, b = 2;
foo(a,b);
cout << "a = " << a << ", b = " << b << endl;
int* p1 = &a;
int* p2 = &b;
foo(p1,p2);
cout << "a = " << a << ", b = " << b << endl;
fun(&a,&b);
cout << "a = " << a << ", b = " << b << endl;
swap(&a,&b);
cout << "a = " << a << ", b = " << b << endl;
swap(a,b);
cout << "a = " << a << ", b = " << b << endl;
return 0;
}
运行结果
a = 1, b = 2
a = 1, b = 2
a = 10, b = 20
a = 20, b = 10
a = 10, b = 10
C/C++在函数中改变参数值的两种方式:
-
通过指针:传递进参数地址,在函数中通过指针修改参数的值(C和C++都行)
-
通过引用:函数参数类型采用引用的数据类型,这样调用函数时创建的是实参的引用,而不是重新构建一个对象,函数中所有的操作都是对实参本身的操作; (仅允许C++,只有C++才有引用)
3. 函数重载,重写,重定义
3.1 函数重载
同一作用域下,函数名相同,参数不同,返回类型的可相同可不同的函数,构成函数重载,单纯的返回值类型不同无法构成函数重载:
代码示例:
void foo(int a, int b);
void foo(int a, double b);
int foo(int a, int b); //错误
3.2 函数重定义
子类对于父类中函数重新定义,子类函数名与父类中函数名相同。
示例代码:
#include <iostream>
using namespace std;
class A
{
public:
void foo()
{
cout << "父类函数foo" << endl;
}
};
class B: public A
{
public:
void foo()
{
cout << "子类重定义了函数foo" << endl;
}
};
int main()
{
B b;
b.foo();
return 0;
}
运行结果:
子类重定义了函数foo
上述代码中子类重定义了父类函数foo,虽然子类对象会包含父类对象,但是调用的函数仍是子类的函数。
3.3 函数重写
子类对父类中虚函数进行重写,函数名和参数必须相同,否则就是重载,实现不了多态。
示例代码:
#include <iostream>
using namespace std;
class A
{
public:
virtual void foo()
{
cout << "这是父类虚函数foo" << endl;
}
virtual void fun(int a)
{
cout << "这是父类虚函数fun" << endl;
}
};
class B: public A
{
public:
void foo()
{
cout << "子类重写了函数foo" << endl;
}
void fun()
{
cout << "子类重写了函数fun" << endl;
}
};
int main()
{
A a1;
a1.foo();
a1.fun(11);
cout << endl;
A* a = new B;
a->foo();
a->fun(11);
cout << endl;
B b;
b.foo();
b.fun();
b.A::fun(11);
return 0;
}
运行结果
这是父类虚函数foo
这是父类虚函数fun子类重写了函数foo
这是父类虚函数fun子类重写了函数foo
子类重写了函数fun
这是父类虚函数fun
以上代码中B类对A类中函数foo进行了重写,但是对函数fun没有。使用指向子类对象的指针调用函数foo时调用的是子类重写的函数foo(多态),但是调用函数fun时调用的是A类中的函数fun。在B类中无法调用基类的fun函数(除非使用作用域限定符)。