目录
运算符别名
-
&& -> and
-
|| -> or
-
! -> not
-
& -> bitand
-
^ -> xor
-
{ -> ^%
-
} -> %^
-
[ -> <:
-
] -> :>
#include <iostream> //17per.cpp
using namespace std;
int main(){
int year;
cin >> year;
if(year%4==0 and year%100!=0 or year%400==0){
cout << "闰年" << endl;
}
int arr<:5:> = <%5,4,3,1,2%>; //重命名使用 [] 和 {}
cout << arr<:3:> << endl;
return 0;
}
//个人感觉没啥人会去用这东西 真想把用的人打死
函数
C++中支持重载
-
X-函数名 Y-参数
-
概念:C++中,在同一个作用域下面,函数名相同,参数列表不同,即构成重载
-
前提条件:在同一个作用域下面 平等关系 (如果作用域不同,不是重载)
-
函数名相同 函数名(一模一样)
-
-
参数列表不同:
-
参数类型不同(对应位置)
-
参数个数不同
-
常属性不同 (指针和引用类型的常属性不一样)
-
-
与函数返回值类型无关
#include <iostream> //18overload.cpp using namespace std; int max(int a,int b){ cout << "int,int" << endl; return a>b?a:b; } int max(int a,int b,int c){ cout << "int,int,int" << endl; if(a>=b && a>=c) return a; if(b>=a && b>=c) return b; return c; } double max(double a,double b){ cout << "double,double" << endl; return a>b?a:b; } int main(){ cout << max(1,2) << endl; cout << max(1,2,3) << endl; cout << max(3.14,3.33) << endl; return 0; }
-
重载错误:
-
重定义(一模一样)
-
新定义(不能变化返回值类型)
-
-
C++中,在调用重载的函数时,在编译阶段根据函数调用时所传递参数的个数和类型来决定调用重载函数
#include <stdio.h> //19func.cpp void func(){ } int main(){ return 0; } /* //19func.s .file "19func.c" .text .globl func .type func, @function func: //宏定义的名字 .LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 popl %ebp .cfi_def_cfa 4, 4 .cfi_restore 5 ret .cfi_endproc .LFE0: .size func, .-func .globl main .type main, @function main: .LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 movl $0, %eax popl %ebp .cfi_def_cfa 4, 4 .cfi_restore 5 ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3" .section .note.GNU-stack,"",@progbits */
-
静态绑定:在编译阶段确定调用哪一个函数
-
动态绑定:在运行阶段确定调用哪一个函数 (多态实现的一种形式)
-
优点:
-
能够提高代码的可用性,使代码更加灵活。
-
多态是设计模式的基础,能够降低耦合性。
-
-
缺点:
-
需要查找虚函数表来,性能比静态函数调用低。
-
虚函数表本身需要存储空间。
-
-
-
C++中为什么可以支持重载?
-
g++编译器会对程序中的函数名进行换名操作,将参数列表中的类型信息汇合到函数名中,以保证函数名的唯一
#include <iostream> //19overload.cpp 验证换名操作 using namespace std; struct Stu{ int no; char name[40]; }; void func(){ cout << "func()" << endl; } //重定义 /* void func(){ cout << "func()" << endl; } */ //新旧定义歧义 /* int func(){ return 1; } */ void func(int a){ cout << "func(int)" << endl; } void func(double b){ cout << "func(double)" << endl; } void func(char a){ cout << "func(char)" << endl; } void func(char a,char b){ cout << "func(char,char)" << endl; } void func(double a,double b){ cout << "func(double,double)" << endl; } void func(int a,int b){ cout << "func(int,int)" << endl; } /* void func(const int a){ cout << "func(const int)" << endl; } */ void func(Stu& s){ cout << "func(Stu)" << endl; } void func(const Stu& s){ cout << "func(const Stu)" << endl; } void func(int *pi){ } void func(const int *pi){ } void bar(int& x){ } void bar(const int& x){ } int main(){ func(); func('a');// func(108); func(3.14); func('a','b'); //func(97,'b');//歧义 func(65.2,77.3); return 0; } /* // 19overload.s 由于.s文件过于长且繁琐 这里截取部分说明 .file "19overload.cpp" .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .section .rodata .LC0: .string "func()" .text .globl _Z4funcv .type _Z4funcv, @function _Z4funcv: //可以发现针对不同形参列表的func会有不同的函数名 如此就构成了重载 .LFB966: _Z4funci: .LFB967: _Z4funcd: .LFB968: _Z4funcc: .LFB969: _Z4funccc: .LFB970: _Z4funcdd: .LFB971: _Z4funcii: .LFB972: _Z4funcR3Stu: .LFB973: _Z4funcRK3Stu: .LFB974: _Z4funcPi: .LFB975: _Z4funcPKi: .LFB976: _Z3barRi: .LFB977: _Z3barRKi: .LFB978: */
-
C++可以不换名吗?
-
可以,extern "C" 要求g++编译器不要对函数进行C++的换名操作,只对一个函数起作用,如果要全部需要加上{}包含函数名
-
以方便C语言中调用C++编译生成的代码
#include <iostream> //20extern_overload.cpp using namespace std; extern "C" void func(){//没有 } void bar(){//变了 } extern "C"{ void call(){}//没有 void hello(){}//没有 } int main(){ return 0; } /* 20extern_overload.s .file "20extern.cpp" .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .text .globl func .type func, @function func: //由于加了extern使得不能重载操作 .LFB966: _Z3barv: .LFB967: call: .LFB968: hello: .LFB969: main: .LFB970: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 movl $0, %eax popl %ebp .cfi_def_cfa 4, 4 .cfi_restore 5 ret .cfi_endproc */
-
-
- 重载时函数调用匹配问题:
-
如果在匹配过程中,没有完全的匹配,会对参数进行隐式转换
-
如果隐式转换的过程中,发现有两个或者及其以上的函数,都能够进行相同次数转换的调用,就会产生歧义
-
-
有常属性的指针和引用 可以和没有常属性的指针和引用 的函数构造重载
-
如果非const版本和const版本都有,那么在调用时根据常属性进行匹配调用
-
没有const属性的指针和引用可以调用 const版本的函数,但是有const属性的指针和引用不能调用非const版本的函数
-
const属性可以自动提升,但const属性不能去除
-
如果只有一个版本的函数,没有常属性的数据可以调用const版本的,有const属性的数据一定不能调用没有const版本的函数,可以自动加强const属性,但是不能贸然丢失const属性
#include <iostream> //21const.cpp using namespace std; /* void func(int *p){ cout << "func(int *)" << endl; } */ void func(const int *p){ cout << "func(const int *)" << endl; } int main(){ int *p1; const int *p2; func(p1);//自动提升const func(p2); return 0; }
-
先进行精确匹配,参数个数和类型完全一样
#include <iostream> //22namespace_and_overload.cpp using namespace std; namespace s1{ void func(int a){ cout << "int:" << a << endl; } } namespace s2{ void func(double d){ cout << "double:" << d << endl; } } int main(){ s1::func(1);// 1 s1::func(3.14);// 3 s2::func(1);//1 s2::func(3.14);//3.14 using namespace s1; func(1);//int:1 func(3.14);//int:3 using namespace s2; func(1);//int:1 func(3.14);//double:3.14 using s1::func; func(1);//int:1 func(3.14);//int:3 using s2::func; func(1);//int:1 func(3.14);//double:3.14 return 0; }
-
-
C++中支持(默认值)缺省值
-
在定义函数时,可以给函数参数以默认值(相当于赋值语句一样),那么在调用该函数时
-
1.可以传递该位置的参数,也可以不传递(取缺失值)
-
2.如果某个函数的一个参数有缺省值,那么该参数后面所以的参数都必须要有缺省值,缺省值"靠右原则"
-
3.如果函数的声明和定义分开的情况下,那么缺省参数只能放在声明中!!!
-
4.要注意和重载函数不产生歧义
#include <iostream> //23default.cpp using namespace std; //参数y有缺省值 该参数可以传 也可以不传 不传的采用的缺省值 long long int pow(int x,int y=2){ long long int res = 1; int i; for(i=1;i<=y;i++){ res *= x; } return res; } // 和缺省值产生了歧义 long long int pow(int x){ } /* void func(int x=1,int y){//如果允许 func(2) } */ //声明 void func(int x,int y=1); void bar(int x,int y=1,int z=2,int w=3){ cout << x << "," << y << "," << z << "," << w << endl; } int main(){ //cout << pow(10) << endl;//调用歧义 cout << pow(10,2) << endl; cout << pow(10,3) << endl; //bar(); bar(0);//0,1,2,3 bar(100,200);//100,200,2,3 bar(100,200,300); return 0; } //void func(int x,int y=1){//分开的情况下,缺省值只能放声明中 void func(int x,int y){ }
C++支持哑元
-
函数的参数只有类型,没有名字的形参,称之为哑元
-
在重载++、--运算符时会使用哑元
-
注意重载产生重定义
#include <iostream> //24yayuan.cpp 对不起英语太差了 using namespace std; void func(void){ } void func(int){//int cout << "func(int)" << endl; } /* void func(int x){ } */ int main(){ func(1); func(2); return 0; }
C++支持内联
-
C++ inline声明的函数
-
1.在调用内联函数时,用函数的二进制指令代码替换掉函数调用指令,减少函数调用的时间的开销,把这种策略称为内联
-
2.inline关键字,只是建议编辑器将指定的函数编译成内联,但仅仅是建议而已
-
3.频繁调用的简单函数适合内联,而稀少调用的复杂函数不适合内联
-
4.调用函数无法内联
C与C++的隐式声明
-
C语言函数的隐式声明,C++没有隐式声明,C++中调用的函数必须先声明
-
C++中如果声明函数的参数为空(啥也没写),就代表了C语言中void的作用
-
C++中不能在调用无参函数时传递实参
#include <iostream> //25function.cpp using namespace std; void func(); int bar(){ } int main(){ //func(1,2,3); bar(); return 0; } void func(){ }
-