函数重载
2016-06-16 02:23
162 查看
一 概念
同一作用域的一组参数列表不同,函数名相同的函数 这组函数叫
函数重载(C++允许定义相同名称的函数)
作用:
重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,
避免了名字空间的污染,对于程序的可读性有很大的好处(一物多用)
参数列表不同:
1 参数类型不同
2 参数顺序不同
3 参数个数不同
重载版本根据参数的匹配度进行选择
注意:
1.1 与函数参数的变量名无关
1.2 函数的返回值类型与重载无关
2 函数重载的实现原理是通过c++换名实现的
extern “C” int fun() 的形式可以以c的方式生成函数名(无换名机制)
3 使用场景:
当函数基本上执行相同的任务 使用不同形式的数据时
二 哑元函数
哑元函数:参数只有类型没有形参名的函数
void fun(int);
功能:1 保持向前兼容性
2 做函数的区分
T operator++() {}
T operator++(int){}
三 缺省参数
如果函数的形参有缺省值,当函数调用时没有传递实参,那么形参就使用缺省
值,如果调用函数时传递了实参,那么形参就使用实参的值
注意:
1 缺省参数靠右原则 如果一个函数有多个参数 且部分参数有缺省值那么缺
省值的参数必须靠右(在编译期间确定参数)
2 如果函数的声明和定义分开 那么缺省参数只能写在函数的声明部分
3 注意防止重载的冲突(歧义)
4 c++中函数的规则 不接受任何参数(否则可能构成重载)
5 凼数参数的缺省值叧能在凼数声明指定
四 内联
函数使用关键字inline 关键字修饰的函数叫做内联函数
函数调用过程 :调用用后立即存储该指令的内存地址
将函数参数复制到堆栈
跳到标记函数起点的内存单元 执行函数代码(可能还有返回
值放入到寄存器中)
将返回值弹出
然后跳回到地址被保存的指令处
内联的实质:
就是把函数编译好的二进制代码 替换成函数的调用指令(省去了调用开销)
(空间换取时间)
注意:
1类中直接定义的函数自动被处理成内联函数,所以一般把内联函数放在头文
件中
2 inline是一种请求,实现方式取决于编译器,特别是当函数较大或是递归
的时候
同一作用域的一组参数列表不同,函数名相同的函数 这组函数叫
函数重载(C++允许定义相同名称的函数)
作用:
重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,
避免了名字空间的污染,对于程序的可读性有很大的好处(一物多用)
参数列表不同:
1 参数类型不同
2 参数顺序不同
3 参数个数不同
重载版本根据参数的匹配度进行选择
注意:
1.1 与函数参数的变量名无关
1.2 函数的返回值类型与重载无关
2 函数重载的实现原理是通过c++换名实现的
extern “C” int fun() 的形式可以以c的方式生成函数名(无换名机制)
3 使用场景:
当函数基本上执行相同的任务 使用不同形式的数据时
二 哑元函数
哑元函数:参数只有类型没有形参名的函数
void fun(int);
功能:1 保持向前兼容性
2 做函数的区分
T operator++() {}
T operator++(int){}
三 缺省参数
如果函数的形参有缺省值,当函数调用时没有传递实参,那么形参就使用缺省
值,如果调用函数时传递了实参,那么形参就使用实参的值
注意:
1 缺省参数靠右原则 如果一个函数有多个参数 且部分参数有缺省值那么缺
省值的参数必须靠右(在编译期间确定参数)
2 如果函数的声明和定义分开 那么缺省参数只能写在函数的声明部分
3 注意防止重载的冲突(歧义)
4 c++中函数的规则 不接受任何参数(否则可能构成重载)
5 凼数参数的缺省值叧能在凼数声明指定
四 内联
函数使用关键字inline 关键字修饰的函数叫做内联函数
函数调用过程 :调用用后立即存储该指令的内存地址
将函数参数复制到堆栈
跳到标记函数起点的内存单元 执行函数代码(可能还有返回
值放入到寄存器中)
将返回值弹出
然后跳回到地址被保存的指令处
内联的实质:
就是把函数编译好的二进制代码 替换成函数的调用指令(省去了调用开销)
(空间换取时间)
注意:
1类中直接定义的函数自动被处理成内联函数,所以一般把内联函数放在头文
件中
2 inline是一种请求,实现方式取决于编译器,特别是当函数较大或是递归
的时候
#include<iostream> using namespace std; namespace overload{ void add(int a, int b){ cout << "int:"<<a + b << endl; } void add(double a,double d){//变量名可以不同 cout << "double:" << a + d << endl; } void add(int a, double d){ cout << "int double:" << a*d << endl; } } namespace show{ void print(char c){ cout << "show1 =" << c << endl; } void print(char c, char d){ cout << "show2 =" << c << d << endl; } } void fun(int a, int b){ cout << "fun1:" << a + b << endl; } /*int fun(int a, int b){ cout << "fun2:" << endl; return a*b; }是参数不同 与函数返回值类型无关*/ int fun(int a, double b){ cout << "fun2:" << a*b<<endl; return 0; } int main(){ using namespace overload; add(1, 2); add(3.1, 4.1); add(1, 2.0); //add("abc", 2); 参数类型 无法进行匹配 show::print('a'); show::print('a', 'b'); fun(5, 6); fun(5, 6.1); //add("abc", 2.1);无法匹配 void(*paddII)(int, int) = add;//根据函数指针类型中的参数表信息确定其他所指向的重载版本 void(*paddDD)(double, double) = add; void(*paddID)(int, double) = add; cout << "-------" << endl; paddII(3, 4); paddDD(3.3, 4.4); paddID(2, 3.3); //paddID('a');// system("pause"); return 0; }
#pragma comment(lib,"CPP.lib") int main(){ cout << "max=" << max(1, 2) << endl; // cout << "max=" << max(1.1, 2.2) << endl; system("pause"); return 0; } //vim add.c //add(int i,int j){ // return i+j; //} //cp add.c add.cpp //gcc -c add.c_ //nm add.o //000000000 (编译模块的相对地址) T (代码段test) add //g++ -c add.cpp //nm add.o // T _Z3addii ii(int int) // T _Z3adddd (double double) // _Z 编译标记 每个编译器不一样 3 函数名长度 // // 我是一个C程序员 写一个程序 调用 // vim main.c // #include<stdio.h> // int add(int ,int); // int main(){ // printf("%d\n",add(123,456)); // return 0; // } // gcc main.c add.oc // gcc -c main.c // nm main.o // U add U 外部 没换名 // //
#include<iostream> using namespace std; void fun(short s = 0, int i = 1, double d = 2.2); /*void fun(short s = 0, int i = 1, double d = 2.2){ cout <<"fun(short,int,double):"<< s<<" "<<i<<" " << d << endl; }*/ /*void fun(short s = 0, int i = 1 ){//ambiguous call to overloaded function cout << s << " " << i << " " << endl; }*/ void bar(short s , int i , double d = 2.2){//靠右原则 windows的很多函数 的带缺省值的都放在后面 cout << "bar(short,int,double):" << s << " " << i << " " << d << endl; } void fun(void){ cout << "fun(void)" << endl; } /*void foo(const int ){//数据类型一样,但属性不一样 和下面的不能进行重载the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called cout << "foo(const int )" << endl; }*/ void foo( int ci){ cout << "foo(int )" << endl; } void foo(const int* ci){ // 引用类型的可以 cout << "foo(const int )" << endl; } void foo(int* ci){ cout << "foo(int )" << endl; }//Inparticular, for any type T, “pointer to T, ” “pointer to const T, ” and “pointer to volatile T” areconsidered distinct parameter types, as are “reference to T, ” “reference to const T, ” and “reference tovolatile T.” int main(){ int i = 0; const int*ci = &i; foo(&i); foo(ci); fun(1,2,3.0); fun(1, 2); fun(1); //fun(); bar(1,2);//重载冲突 getchar(); return 0; } void fun(short s /*=0*/, int i/*=1*/, double d /*=2.2*/){//函数定义时可以不写缺省参数 cout << s << " " << i << " " << d << endl; }
#include<iostream> using namespace std; //version 1.0 向下兼容 /*void compress(string s){ cout << "compress.." << "finish" << endl; }*/ //version 2.0 void compress(string){ cout << "compress.." << "finish" << endl; } //-----区分重载版本 void fun(int x, int y){ cout << "fun1:"<<x<<' '<<y << endl; } void fun(int x, int y, int){ cout << "fun2:" <<x<<' '<<y<< endl; }//上面两个函数换一下名就可以 //-----但有的时候函数名只能用一个。。operator++ int main(){ compress("abc"); compress("sdflj"); fun(1, 2); fun(1, 2, 3); getchar(); return 0; }
#include<iostream> #define ADD(a,b) (a+b) //宏不能访问对象的私有成员 宏的定义很容易产生二义性(MUL(X) (X*X)) MUL(10+10) === 10+10*10+10 using namespace std; inline int add(int a,int b){//在类里定义的成员函数会被隐含指定为内置函数 return a + b; } inline int foo(int i){ /*if (i == 1 || i == 2){ return 1; }*/ return (i==1||i==2)?1:(foo(i-1) + foo(i - 2)); } class UPInt { public: UPInt() { m_i = 0; } UPInt(int value) { m_i = value; } //.. friend const UPInt operator+(const UPInt&lhs, const UPInt &rhs); private: int m_i; }; const UPInt operator+(const UPInt&lhs, const UPInt &rhs) { cout << "operator+" << endl; UPInt UPIntTemp(lhs.m_i + rhs.m_i); return UPIntTemp; } //const UPInt operator+(int lhs, int rhs); // 错误!这C++中有一条规则是每一个重载的operator必须带有一个用户定义类型(user-defined type)的参数 int main(){ cout << add(1, 2) << endl; cout << ADD(1, 2) << endl; for (int i = 1; i < 10;i++) cout << foo(i) << endl; UPInt upi1, upi2; UPInt upi3 = upi1 + upi2; upi3 = upi1 + 10;//这些语句也能够成功运行。方法是通过建立临时对象把整形数10转换为UPInts upi3 = 10 + upi2; getchar(); return 0; } /* 1 内联它与一般函数所不同之处只在于函数调用的处理。。编译的时候展开 2 一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换 3 另外内联的函数无法进行断点调试 */
相关文章推荐
- Linux系统之文件类型
- 5分钟搞定一本小说实例续篇
- About New land (Empire Builders)
- iOS_webView
- 关于http keep-alive与tcp keep-alive
- Android WebView 缓存
- Rest API 设计最佳实践(3)
- 关于 Unity3d iOS 9.x支持ipv6
- 最美的东西只能用深痛巨创来换取(之---我是演说家之幕后前台)
- 名字空间
- 理解RESTFul架构
- 思科网络视频记要
- 关于Linux中的补丁命令diff和patch
- 作业九 ——报告及总结
- 解决NDK开发中Eclipse报错“Unresolved inclusion jni.h”的最终方法
- ios学习路线—Objective-C(生命周期)
- 机电传动控制——直流电机调速仿真实验
- 作业九:报告及总结
- iOS--UIButton图片在上,文字在下
- iOS--UIButton图片在上,文字在下