首页 > 编程语言 >C++基础入门(4)

C++基础入门(4)

时间:2024-07-16 20:27:19浏览次数:21  
标签:入门 int 基础 C++ 参数 func 重载 函数

一.函数重载

C语言实现int,double,char类型的比较大小函数。

int my_max_i(int a,int b){return  a>b?a:b;}
double my_max_d(double a,double b){return a>b?a:b;}
char my_max_c(double a,double b){return a>b?a:b;}

这些函数都执行了相同的动作,返回两个形参中的最大值;从用户的角度来看,只有一种操作,就是判断最大值。

这种词汇上的复杂性不是“判断参数最大值”问题固有的,而是反映了程序设计环境 的一种局限性:在同一个域中出现的名字必须指向一个唯实体(函数体)。

这种复杂性给程序员带来了一个实际问题,他们必须记住每一个函数的名字。

函数重载把程序员从这种词汇的复杂性中解放出来。

1.1函数重载的概念

在C++中可以为两个或两个以上的函数提供相同的函数名称,只要参数类型不同,或者参数类型相同而参数的个数不同,称为函数重载。(函数名相同)

int max(int a,int b)
{
  return a>b?a:b;
}
double max(double a,double b)
{
  return a>b?a:b;
}
char max(char a,char b)
{
  return a>b?a:b;
}
//每个同名函数的参数表是唯一
int main()
{
  cout<<max(12,23)<<endl;
  cout<<max('a','b')<<endl;//''是 字符的定界符""是字符串的定界符
  cout<<max(12.23,34.45)<<endl;
}

如果两个函数的参数表中参数的个数或类型或顺序不同,则认为这两个函数是重载。

void print(int a,char b);
void print(char a,int b);

函数原型:返回值,函数名,形参表。

这两个从函数原型上是不同的。

1.2判断函数重载的规则

1.2.1函数重载不用返回值作为重载的依据

如果两个函数的参数表相同,但是返回类型不同,会被标记为编译错误:函数的重复声明。

int Max(int a,int b)
{
  return a>b?a:b;
}
char Max(int a,int b)//error
{
  return a>b?a:b;
}

1.2.2参数表的比较过程与形参名无关

//同一个函数
int add(int a,int b);
int add(int x,int y);

1.2.3如果在两个函数的 参数表中,只有缺省实参不同,则第二个声明被视为第一个重复声明

void print(int *br,int n);
void print(int *br,int len=10);

这两个是同一个函数

1.2.4typedef

用typedef做了替换名,但并没有创建一个新类型,也是相同的函数。

typedef unsigned int u_int;
int print(u_int a);
int print(unsigned int b);

1.2.5const volatile(多线程)

int func(int a)
{}
int func(const int b)
{}
int main()
{
  func(12);
}

这种情况下会出现二义性的问题,所以在这种情况下,形参表中的const并不作为区分的标志。

但是常性左值引用的左值引用可以最为区分的标志。

​int func(int &a)
{}
int func(const int &b)
{}
int func(int &&c)
{}
int main()
{
  func(12);
}

​

同理,在左值引用,右值引用和右值常引用之间,如果是一个左值,优先关联左值引用,左值常引用退而求其次,右值同理。

​void func(int *ap)
{}
void func(const int *bp)
{}
int main()
{
  int a=10;
  func(&a);
}

在这种情况下,指针中的const也作为函数重载的标志。

void func(int *ap)
{}
void func(int * const bp)
{}
int main()
{
  int a=10;
  func(&a);
}

但当const是修饰指针自身的时候,忽略const,这个还是有二义性的。

1.2.6注意函数调用的二义性

如果两个函数的参数表中,形参类型相同,而个数不同,形参默认值将会影响函数重载。

void func(int a){};
void func(int a,int b=10){};
int main()
{
  func(12);
  func(12,23);
}

这样就会出现二义性的问题。

二、名字粉碎(名字修饰)

C或者C++函数在 内部(编译和链接)通过修饰名 识别。修饰名是编译器在编译函数定义或者原型时生成的字符串。

修饰名由函数名,类名,调用约定,返回值类型,参数表共同决定。

调用约定:
__stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。

什么是从右到左的压栈方式呢?

int Add(int x,int y)
{
  int z=x+y;
  return z;
}
int main()
{
  int a=10,b=20;
  int c=0;
  c=Add(a,b);
  printf("c=%d",c);
  return 0;
}

在调用函数的时候,是先用b对y赋值再用a对x赋值

EIP指令地址寄存器,就是关联到代码执行的位置。

C调用约定(即用__cddecl关键字说明)按照从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。

__fastcall调用约定,它的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈),在函数名修饰约定方面,它和两者均不同。

thiscall仅仅应用于“C++”类的成员函数。this指针存放于ECX寄存器,参数从右向左压。thiscall不是关键词,因此不能被程序员指定。

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预编译(预处理),编译,汇编,链接。

2.1C语言编译时函数名修饰约定规则

C语言的名字修饰规则非常简单,_cdecl是C/C++的缺省调用方式,调用约定函数名字前面添加了下划线前缀。

格式:_functioname

_stdcall调用约定在输出函数名前面加上一个 下划线前缀,后面加上 一个“@”符号 和其参数的字节数。

格式:_functioname@number

__fastcall调用约定在输出函数名前面加上“@”符号,函数后面也是一个“@”符号和其参数的字节数。

格式:@func@number

2.2C++编译时函数修饰约定规则

PA——表示指针,后面的代号表明指针类型,如果相同 类型的指针连续出现,以“0”代替,一个“0”代表重复一次。

4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前。

5、参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。

所以在这种情况下,返回值不能作为重载的依据,因为在底层区别不出来

这也是c++可以进行函数重载但是C语言不行的原因。因为名字粉碎技术不同。所以在编译过程中C++可以区分出来不同而C语言不可以。

外部关键字的用法:

extern其实就是一个声明,明确指出一个语句是声明,比如extern int i ;这是声明变量i,而不是定义i,定义i则是int i声明不开辟内存空间,而定义是要开辟内存空间的

两者 extern 和 extern"C"有点区别:
extren 在C和C++中,都表示声明语句的意思;
而 extern"C"是按C语言方式去编译文件;
extern"C"只能在C++文件使用,extern在C和C++都可以使用
 

在 函数前面加上

extern"C":函数名以C的方式进行修饰约定规则

extern"C++":函数名以C++的方式进行修饰约定规则

三、函数模板

为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数据类型改为一个设计参数。这种类型的程序设计称为参数化程序设计。

软件模块由模板(template)构造。包括函数模板和类模板。

函数模板可以用来创造一个通用功能的函数。以支持多种不同形参,简化重载函数的设计。、

函数模板的定义如下:

template<模板参数表>
返回类型 函数名(形式参数表)
{
  ...;//函数体
}

当编写了这样一个函数时,在编译过程中会变成这样:

实质上还是函数的重载,只不过是编译器自己生成。

函数模板根据一组实际类型或值构造出独立的函数的过程通常是隐式发生的,称为模板实参推演

函数模板的重载(特化)

标签:入门,int,基础,C++,参数,func,重载,函数
From: https://blog.csdn.net/2302_80090192/article/details/140471909

相关文章

  • Java基础-学习笔记04
    04运算符进制1.运算符逻辑与&和短路与&&共同点:两个条件都为true时,结果为true,否则为false。&逻辑与:不管第一个条件是否为false,第二个条件都要判断;&&短路与:如果第一个条件判断为false,则第二个条件不会判断。逻辑或|和短路或||共同点:两个条件只要有一个成立,结果......
  • python 基础知识点(一)
    1.Python可以将一条长语句分成多行显示的续行符号是 \2.缩进可以用tab键实现,也可以用多个空格实现3.在Python中,使用缩进对齐来标记语句块4.在Python中,使用缩进对齐来体现代码之间的逻辑关系。5.严格的缩进可以约束程序结构,可以多层缩进6.Python中......
  • TS 入门(五):TypeScript接口与类
    目录前言回顾高级类型与类型操作1.接口a.基本接口b.可选属性和只读属性c.函数类型接口d.可索引类型e.接口继承2.类a.基本类b.类的成员(属性和方法)c.构造函数d.继承和派生类e.公有、私有和受保护的修饰符f.静态属性和方法g.抽象类扩展知识点:接口与类的结合......
  • 算法入门-数组2
    第一部分:数组26.删除有序数组中的重复项(简单)题目:给你一个非严格递增排列的数组nums,请你 原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致。然后返回nums中唯一元素的个数。考虑nums的唯一元素的数量为k,你......
  • Windows图形界面(GUI)-DLG-C/C++ - 列表框(ListBox)
    公开视频-> 链接点击跳转公开课程博客首页-> ​​​​​​链接点击跳转博客主页列表框(ListBox)控件类型单选列表框(Single-selectionListBox):用户一次只能选择一个列表项。它通常用于当选择范围被限定到一个单一的选项时。多选列表框(Multi-selectionListBox):用户可以同......
  • Windows图形界面(GUI)-DLG-C/C++ - 静态控件(Static)
    公开视频-> 链接点击跳转公开课程博客首页-> ​​​​​​链接点击跳转博客主页目录静态控件(Static)控件样式消息处理实例代码静态控件(Static)控件样式文本(Text):用来显示文本信息。可以是简单的一行文本或者复杂的格式化文本。图标(Icon):用来显示一个小图标,常用......
  • C++ OPENGL 贝塞尔曲线绘制
    代码 #include<glad/glad.h>#include<GLFW/glfw3.h>#include<iostream>#include<vector>structPoint{floatx;floaty;};//二次贝塞尔Pointbezier(floatt,Pointa,Pointc,Pointz){return{(1-t)*(1......
  • C++自定义双向迭代器
    #include<cassert>#include<memory>#include<vector>#include<iostream>classRange{public:usingIndex=uint64_t;usingSignedIndex=int64_t;usingOffset=int64_t;usingSize=uint64_t;Range()=d......
  • python 基础之 scrapy 当当数据一演示
    Items程序importscrapyclassDangdangItem(scrapy.Item):#definethefieldsforyouritemherelike:#name=scrapy.Field()src=scrapy.Field()name=scrapy.Field()price=scrapy.Field()spider程序importscrapyclassDangSpider(......
  • C++(3) 3D-3D ICP SVD RANSCE
    CMakeLists.txtcmake_minimum_required(VERSION3.5)project(ICP_SVD_example)#SetC++standardtoC++11set(CMAKE_CXX_STANDARD11)set(CMAKE_CXX_STANDARD_REQUIREDON)#FindEigenlibraryfind_package(Eigen3REQUIRED)#IncludedirectoriesforEigeni......