C++之引用&重载
2016-10-15 01:21
183 查看
1.引用(reference )的概念:
引用是一个目标的别名;目标可以是变量或对象;
2.声明引用的符号为&,引用开始必须初始化;(将引用与一个目标进行绑定);
3.操作引用就是操作目标本身,反之亦然;
4.一个目标可以有多个引用;(就像一个人可以有多个别名一样)
5.一个引用不能同时绑定多个目标;
6.有指针的引用,例如:int *&t_p1 = t_p2;
7.没有数组的引用,没有void引用;但是可以有引用的数组
8.引用的类型必须和目标的类型一样;
9.常引用(const引用):作用不能通过const引用来修改被绑定目标的值;
int t_a = 200;
int t_b = 300;
const int &t_c = t_a;
//t_c = 400; is error , t_c read-only reference
t_a = 400;
10.引用作为函数的参数的好处:减少拷贝,提高效率;
11.引用作为函数的返回值的好处:减少一次拷贝,提高效率;注意当函数的返回值为引用类型时,不要将一个临时变量返回出去;
12.内联函数:1~5行的代码量的小函数适合作为内联函数;原理就是代码替换
好处:提高代码的执行效率,以时间换空间;
内联函数的声明和定义必须放在一个文件里,inline关键字是建议C++编译器将该函数搞为内联函数,但没有决定权;当函数里面有循环语句,复杂的条件语句,递归等,则C++编译器无视inline关键字,将该函数作为普通函数处理;
13.函数重载:满足函数重载的条件,有相同的函数名,不同的形参列表;与函数的返回值无关;如果该函数有默认参数,则重载该函数的时候,需要特别注意;
14.递归函数:自己调用自己的函数,注意必须要有退出函数的条件判断;
15.函数的默认参数:函数可以有自己的默认参数,例如int add(int t_a = 10,int t_b = 20,int t_c = 30, int t_d = 40);
如果这样调用add(),则参数全部用的是默认值10,20,30,40;
如果是这样调用add(50),则后面3个参数用默认的20,30,40,依次类推;注意我们给函数增加默认参数时,必须从右往左添加,例如int add(int t_a,int t_b,int t_c,int t_d = 10)是正确的,而int
add(int t_a = 30,int t_b,int t_c,int t_d)是错误的,编译不过,因为当传递实参时,编译器会自左向右与形参进行匹配。例如add(1,2,3)这样传参的话,则t_a=1,t_b=2,t_c=3,那t_d就没有值了,那这种情况下就必须传递4个参数,而这样又违背了默认参数的初衷,初衷是可以传递3个参数的;所以编译器不允许程序员这么做,因为这么做函数默认参数就毫无意义了。
16.关于函数传参的总结:基本类型(int,char,double),枚举类型一般用值传递,结构/类的对象一般用引用或指针传递,数组类型一般用指针传递;
17.形参是引用传递时,一般将形参设置为const类型的引用,这样的好处是防止在函数中误操作,将实参的值修改了;
练习:
设计一个函数,函数的返回值为引用,返回两个字符串中长度最大的字符串;
const string& maxString(const string &t_str1, const string &t_str2)
{
return t_str1.length() > t_str2.length() ? t_str1 : t_str2;
}
错误示例:
1.声明引用时没有初始化,在qt编译器下,有如下警报:
D:\QQPCmgr\Desktop\C++_Prj\Reference\main.cpp:10: 错误:'t_c' declared as reference but not initialized
在Linux下g++编译器的错误提示:
reference.cpp:9:7: error: ‘t_c’ declared as reference but not initialized
引用就是某一个变量的别名,引用的地址就是原变量的地址,引用的值就是原变量的值
不能建立引用的数组,例如:int & ref[3] = { 2, 3, 5}; //声明ref引用的数组是错误的
但是可以建立数组的引用:例如:int arr[3]; int (&tef)[3] = arr; //这是这是正确的
为什么数组中的元素不能是引用?
c++中,引用可以说只是某个变量的别名,所谓别名,是和指针类型区分开的:
指针类型也可以指向某个变量,但指针类型本身也是一个变量,而引用实际上不是一个变量。更本质来说,可以理解为引用没有自身的地址,不占用内存空间(这里为了简化问题可以这样考虑)。因此,声明引用数组没有办法分配空间,因为根本就没有空间可以分配给引用。所以不能声明和定义引用数组
函数重载(overload):将语义,功能相似的几个函数用同一个名字来表示
易用性
构造函数需要重载机制,c++规定构造函数与类同名,且只能有一个名字
规则:
由函数接口(参数,返回值)区别重载函数,显然,返回值无法让编译器和程序员知道哪个函数被调用,因为c/c++中返回值有时可悲忽略!
假设某个c函数如下:
void foo(int x, int y);
该函数在c编译器编译后在库中的名字为_foo,而c++编译器则会产生_foo_int_int之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同,故然c++不能直接调用c函数。
提供了一个c连接交换指定符号extern “C”
注意:
并不是两个函数的名字相同就构成函数重载,全局函数和成员函数同名不算重载,不在同一作用域!
全局函数被调用是要加上域作用符“::”
隐式类型转换会导致重载函数产生二义性
成员函数被重载的特征:
1.相同的范围(在同一类中)
2.函数名字相同
3.参数不同
4.virtual关键字可有可无
[align=left]覆盖是指派生类函数覆盖基类函数,特征是:[/align]
[align=left](1)不同的范围(分别位于派生类与基类);[/align]
[align=left](2)函数名字相同;[/align]
[align=left](3)参数相同;[/align]
(4)基类函数必须有virtual
关键字。
代码示例:
Makefile文件:
引用是一个目标的别名;目标可以是变量或对象;
2.声明引用的符号为&,引用开始必须初始化;(将引用与一个目标进行绑定);
3.操作引用就是操作目标本身,反之亦然;
4.一个目标可以有多个引用;(就像一个人可以有多个别名一样)
5.一个引用不能同时绑定多个目标;
6.有指针的引用,例如:int *&t_p1 = t_p2;
7.没有数组的引用,没有void引用;但是可以有引用的数组
8.引用的类型必须和目标的类型一样;
9.常引用(const引用):作用不能通过const引用来修改被绑定目标的值;
int t_a = 200;
int t_b = 300;
const int &t_c = t_a;
//t_c = 400; is error , t_c read-only reference
t_a = 400;
10.引用作为函数的参数的好处:减少拷贝,提高效率;
11.引用作为函数的返回值的好处:减少一次拷贝,提高效率;注意当函数的返回值为引用类型时,不要将一个临时变量返回出去;
12.内联函数:1~5行的代码量的小函数适合作为内联函数;原理就是代码替换
好处:提高代码的执行效率,以时间换空间;
内联函数的声明和定义必须放在一个文件里,inline关键字是建议C++编译器将该函数搞为内联函数,但没有决定权;当函数里面有循环语句,复杂的条件语句,递归等,则C++编译器无视inline关键字,将该函数作为普通函数处理;
13.函数重载:满足函数重载的条件,有相同的函数名,不同的形参列表;与函数的返回值无关;如果该函数有默认参数,则重载该函数的时候,需要特别注意;
14.递归函数:自己调用自己的函数,注意必须要有退出函数的条件判断;
15.函数的默认参数:函数可以有自己的默认参数,例如int add(int t_a = 10,int t_b = 20,int t_c = 30, int t_d = 40);
如果这样调用add(),则参数全部用的是默认值10,20,30,40;
如果是这样调用add(50),则后面3个参数用默认的20,30,40,依次类推;注意我们给函数增加默认参数时,必须从右往左添加,例如int add(int t_a,int t_b,int t_c,int t_d = 10)是正确的,而int
add(int t_a = 30,int t_b,int t_c,int t_d)是错误的,编译不过,因为当传递实参时,编译器会自左向右与形参进行匹配。例如add(1,2,3)这样传参的话,则t_a=1,t_b=2,t_c=3,那t_d就没有值了,那这种情况下就必须传递4个参数,而这样又违背了默认参数的初衷,初衷是可以传递3个参数的;所以编译器不允许程序员这么做,因为这么做函数默认参数就毫无意义了。
16.关于函数传参的总结:基本类型(int,char,double),枚举类型一般用值传递,结构/类的对象一般用引用或指针传递,数组类型一般用指针传递;
17.形参是引用传递时,一般将形参设置为const类型的引用,这样的好处是防止在函数中误操作,将实参的值修改了;
练习:
设计一个函数,函数的返回值为引用,返回两个字符串中长度最大的字符串;
const string& maxString(const string &t_str1, const string &t_str2)
{
return t_str1.length() > t_str2.length() ? t_str1 : t_str2;
}
错误示例:
1.声明引用时没有初始化,在qt编译器下,有如下警报:
D:\QQPCmgr\Desktop\C++_Prj\Reference\main.cpp:10: 错误:'t_c' declared as reference but not initialized
在Linux下g++编译器的错误提示:
reference.cpp:9:7: error: ‘t_c’ declared as reference but not initialized
引用就是某一个变量的别名,引用的地址就是原变量的地址,引用的值就是原变量的值
不能建立引用的数组,例如:int & ref[3] = { 2, 3, 5}; //声明ref引用的数组是错误的
但是可以建立数组的引用:例如:int arr[3]; int (&tef)[3] = arr; //这是这是正确的
为什么数组中的元素不能是引用?
c++中,引用可以说只是某个变量的别名,所谓别名,是和指针类型区分开的:
指针类型也可以指向某个变量,但指针类型本身也是一个变量,而引用实际上不是一个变量。更本质来说,可以理解为引用没有自身的地址,不占用内存空间(这里为了简化问题可以这样考虑)。因此,声明引用数组没有办法分配空间,因为根本就没有空间可以分配给引用。所以不能声明和定义引用数组
函数重载(overload):将语义,功能相似的几个函数用同一个名字来表示
易用性
构造函数需要重载机制,c++规定构造函数与类同名,且只能有一个名字
规则:
由函数接口(参数,返回值)区别重载函数,显然,返回值无法让编译器和程序员知道哪个函数被调用,因为c/c++中返回值有时可悲忽略!
假设某个c函数如下:
void foo(int x, int y);
该函数在c编译器编译后在库中的名字为_foo,而c++编译器则会产生_foo_int_int之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同,故然c++不能直接调用c函数。
提供了一个c连接交换指定符号extern “C”
注意:
并不是两个函数的名字相同就构成函数重载,全局函数和成员函数同名不算重载,不在同一作用域!
全局函数被调用是要加上域作用符“::”
隐式类型转换会导致重载函数产生二义性
成员函数被重载的特征:
1.相同的范围(在同一类中)
2.函数名字相同
3.参数不同
4.virtual关键字可有可无
[align=left]覆盖是指派生类函数覆盖基类函数,特征是:[/align]
[align=left](1)不同的范围(分别位于派生类与基类);[/align]
[align=left](2)函数名字相同;[/align]
[align=left](3)参数相同;[/align]
(4)基类函数必须有virtual
关键字。
代码示例:
//comdef.h(在include文件夹里,makefile中要包含路径) #ifndef _COMDEF_H_ #define _COMDEF_H_ #ifdef _cplusplus extern "C" { #endif extern void mySwap(int *a, int *b); #ifdef _cplusplus } #endif #include <cmath> #define PI acos(-1.0) #endif
Makefile文件:
GOAL := overload_implicit objs := ${GOAL}.o CFLAGS := -I${shell pwd}/include CPP := g++ ${GOAL} : ${objs} g++ $^ -o $@ -lm export CFLAGS CPP %.o : %.cpp ${CPP} ${CFLAGS} -Wall -fpermissive -c $^ -o $@ .PHONY: clean clean: rm -rf ${GOAL} *.
//<strong><span style="font-size: 19px;"></span></strong>overload_implicit.cpp #include <iostream> using namespace std; void output(int n); void output(float n); void output(int n) { cout << "output int: " << n << endl; } void output(float n) { cout << "output float: " << n << endl; } int main(void) { int x = 1; float y = 1.0; output(x); output(y); output(1); return 0; }
//overload_swap.cpp #include <iostream> #include <string> #include <cstring> #include "comdef.h" using namespace std; double g_area; void Print() { cout << "global function" << endl; } class A { public: void Print() { cout << "member function\n"; } }; void mySwap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } void mySwap(int &t_a, int &t_b) { int tmp = t_a; t_a = t_b; t_b = tmp; } const string& maxString(const string &t_str1, const string &t_str2) { return t_str1.length() > t_str2.length() ? t_str1 : t_str2; } double &getArea(double t_r) { g_area = PI * t_r * t_r; return g_area; } int main(void) { cout << "pi = " << PI << endl; int t_a = 100, t_b = 200; cout << "t_a = " << t_a << ", t_b = " << t_b << endl; #if 0 cout << "point swap\n"; mySwap(&t_a, &t_b); cout << "t_a = " << t_a << ", t_b = " << t_b << endl; #endif cout << "reference swap\n"; mySwap(t_a, t_b); cout << "t_a = " << t_a << ", t_b = " << t_b << endl; double t_r = 10.0; double &t_area = getArea(t_r); cout << "area: " << t_area << endl; string t_str1 = "hello"; string t_str2 = "world"; cout << "The Max string 'hello' and 'word' is : " << maxString(t_str1, t_str2) << endl; cout << "=============================\n"; ::Print(); return 0; }
//reference.cpp #include <iostream> #include <string> using namespace std; struct animal { string m_name; int m_weight; int m_age; }; void getAnimalInfo(const animal &t_animal) { cout << "animal name: " << t_animal.m_name << endl; cout << "animal weight: " << t_animal.m_weight << endl; cout << "animal age: " << t_animal.m_age << endl; } void setAnimalInfo(animal &t_animal) { cout << "Please input the animal name: \n"; cin >> t_animal.m_name; cout << "Please input the animal weight: \n"; cin >> t_animal.m_weight; cout << "Please input the animal age: \n"; cin >> t_animal.m_age; } void setAnimalInfo(animal &t_animal, const string &t_name, int t_weight, int t_age) { t_animal.m_name = t_name; t_animal.m_weight = t_weight; t_animal.m_age = t_age; } void setAnimalInfo(animal &t_destAnimal, const animal &t_srcAnimal) { t_destAnimal.m_name = t_srcAnimal.m_name; t_destAnimal.m_weight = t_srcAnimal.m_weight; t_destAnimal.m_age = t_srcAnimal.m_age; } int main(int argc, char *argv[]) { int t_a = 200, t_b = 300; const int &t_c = t_a; t_a = t_b; cout << "&t_a = " << &t_a << " t_a = " << t_a << endl; cout << "&t_c = " << &t_c << " t_c = " << t_c << endl; animal t_animal = {"Tiger", 200, 5}; getAnimalInfo(t_animal); setAnimalInfo(t_animal, "Dog", 100, 10); getAnimalInfo(t_animal); return 0; }
#ifndef FUN2_H
#define FUN2_H
//函数重载
//1.函数名一样 2.函数的形参列表不一样 3.与函数的返回值无关
void Swap(int *t_p1,int *t_p2);
void Swap(int &t_x,int &t_y);
void Swap(int &t_x,int &t_y,bool t_b);
//增加函数的默认参数,必须从右往左添加
//函数传参时,实参匹配形参的顺序是从左往右的
int add(int t_a,int t_b,int t_c,int t_d = 4);
#endif // FUN2_H
相关文章推荐
- c++函数功能 引用 & 重载 & 默认参数 & 内联
- c/c++中结构体引用中箭头->与点.的区别 【转】
- 【C/C++语法外功】传值&传引用&传指针
- 《C++第九周实验报告1-1》--------接第8周任务1,定义Complex类中的<<和>>运算符的重载,实现输入和输出
- C++中函数变量的引用 &
- C++中引用(&)的用法和应用实例
- 读书笔记-Thinking in C++-第7章 函数重载和默认参数Function Overloading &Default Arguments
- C++中重载数组下标访问操作符[ ] 和 赋值操作符 = ,* 和 -> 操作符和取反 !以及转化操作符bool和void*
- 指针&引用在C C++ JAVA 语言特性导致表达能力的差异
- C++中引用和地址运算符 &
- 以实践的方式学习C++ &(引用)
- [转载]c/c++中结构体引用中箭头->与点.的区别
- C++中指针和引用的区别-转载fu_jiangtao<chinaunix>
- "数组引用"以避免"数组降阶"(c++)
- 一个看起来奇怪的C++程序 && c++操作符重载
- C++ 中引用C extern "C" 的用法
- c++学习笔记--引用&
- C++中的&表示引用与取址的用法
- C++ &引用对象
- C++中输入输出<< 和>>重载,以便适应输出输入一个对象