C/C++(C++重载,默认参数,引用)

C++重载详解

重载就是同名而非同义,具体意义根据上下文的语境而言。

重载规则:

1,函数名相同。

2,参数个数不同,参数的类型不同,参数顺序不同,均可构成重载。

3,返回值类型不同则不可以构成重载。

函数重载(静多态)

void print(int a)
{
    //...
}
void print(int a,char b)
{
    //...
}
void print(char a,int a)
{
    //...
}
//根据参数的数序,个数执行上下文。

匹配原则:

1,严格匹配,找到则调用。

2,通过隐式转换寻求一个匹配,找到则调用。

void print(int a)
{
    printf("void print(int a)\n");
}
void print(char a)
{
    printf("void print(char a)\n");
}
void print(float a)
{
    printf("void print(float a)\n");
}
void print(double a)
{
    printf("void print(double a)\n");
}
int main()
{
    printf(3.4);//3.4是double类型,如果上述没有double类型,他会转向int,float类型,但是两者同时又的话,会报错产生二义性,不要让计算机去解决一些事情。
    print(‘a‘);//如果没有char类型最终会转向int类型。字符是以asscII码存在,也就是int类型。
}

int 到 long 和 double,double 到 int 和 float 隐式类型转换。遇到这种情型,则会引起二义性。

如果使用时遇到二义性的,在使用时经过强转即可。

void print(int a)
{
    printf("void print(int a)\n");
}
void print(char a)
{
    printf("void print(char a)\n");
}
void print(float a)
{
    printf("void print(float a)\n");
}
/*void print(double a)
{
    printf("void print(double a)\n");
}*/
int main()
{
    print(3.14);// error: call of overloaded ‘print(double)‘ is ambiguous
    print((int)3.14);
    print((float)3.14);
    /*
    void print(int a)
    void print(float a)
    */
}

重载的原理

name mangling(倾轧)

void print(int a)//print_i
{
    printf("void print(int a)\n");
}
void print(char a)//print_ic
{
    printf("void print(char a)\n");
}
void print(float a)//...
{
    printf("void print(float a)\n");
}
void print(double a)//...
{
    printf("void print(double a)\n");
}
int main()
{
    print(3.14);//重载函数之间底层处理技术倾轧,把相同的函数名倾轧成不同的函数名。
    return 0;
}

声明.h文件

#ifndef PRING_H
#define PRING_H
extern "c"//不倾轧
{
    void print(int a)
    void print(char a)
    void print(int a,char b)
    void print(char a,int b)
}

#endif //PRING_H
#include<iostream>
#include "print.h"
using namespace std;
int main()
{
    int a,char b;
    print(a);
    return 0;
}

函数的定义部分.cpp文件

void print(int a)//print_i
{
    printf("void print(int a)\n");
}
void print(char a)//print_ic
{
    printf("void print(char a)\n");
}
void print(float a)//...
{
    printf("void print(float a)\n");
}
void print(double a)//...
{
    printf("void print(double a)\n");
}

要求是每个倾轧时要同时,不同的话则报错。c++要完全兼容C,标准C库是没有倾轧的。但是写头文件时要包含的c++中,c++便宜的时候就会有倾轧的文件,这时候就会链接不上。所以为了连接上在自己写的头文件上要求不要倾轧。extern "c"或者extern "c" {多行的情况}

操作符重载

C++认为一切操作符都是函数,函数是可以重载的。=>操作符是可以重载的。(并不是所有的运算符都可以重载)

struct Complex{
    float a;
    float b;
}
int main(){
    Complex aa = {1,2},bb = {2,3};
    Complex cc = aa + bb;//error

    return 0;
}

对操作符进行重载

struct Complex
{
    float a;
    float b;
}
Complex operator+(Complex a,Complex b)
{
    Complex c;
    c.a = a.a + b.a;
    c.b = a.b + b.b;
    return c;
}
int main()
{
    Complex aa = {1,2},bb = {2,3};
    Complex cc = aa + bb;//right
    cout<<"cc = "<<"("<<cc.a<<","<<cc.b<<")"<<endl;
    return 0;
}
//cc = (3,5),实现了结构体之间的加法,当然也可以用函数实现一个加法的过程

默认参数(default parameters)

#include<iostream>
#include<time.h>
using namespace std;
void weatherCast(string w = "pm=2.5")//默认参数
{
    time_t t = time(0);//1970,0:0:0的毫秒数
    char tmp[64];
    strftime(tmp,sizeof(tmp),"%Y/%m/%d %x %A",localtime(&t));
    cout<<tmp<<"today is weather "<<w<<endl;
}
int main()
{
    weatherCast();
    weatherCast("sunshine");
    return 0;
}
//2018/03/04 03/04/18 Sundaytoday is weather pm=2.5
//2018/03/04 03/04/18 Sundaytoday is weather sunshine

多参数之间的默认参数,从右至左默认,中间不能跳跃。

实参的个数+默认的参数个数 >= 形参的个数

int volume(int l = 3,int w = 4,int h = 5)
{
    return l*w*h;
}
int main()
{
    cout<<volume()<<endl;
    cout<<volume(2,2)<<endl;
    cout<<volume(2,2,2)<<endl;
    return 0;
}
/*
60
20
8
*/

默认参数与重载的冲突

void print(int a)
{
    printf("void print(int a)");
}
void print(int a,int b = 100)
{
    printf("void print(int a,int b = 100)");
}
int main()
{
    print(1,200);
//void print(int a,int b = 200
    print(1);//报错
    return 0;
}

一个参数或者是两个参数的形式,重载,默认参数都是可以实现的,但是不可以两者同时存在。(在函数重载实现默认参数时要注意,二义性)

引用

变量名,本身是一段内存的引用,即别名(alias)。此处引入的引用,是为己有变量起一个别名。

int main()
{
    int a = 500;//变量名的实质是一段内存空间的别名
    int&ra = a;//ra是a的引用
    printf("sizeof(ra) = %d sizeof(a) = %d\n",sizeof(ra),sizeof(a));
    printf("&a = %p &ra = %p\n",&a,&ra);
    a = 1000;
    printf("a = %d ra = %d\n",a,ra);
    ra = 1000;
    printf("a = %d ra = %d\n",a,ra);

    int b = 200;
//    int&ra = b;//报错
    ra = b;//这是赋值

    int&rb = ra;
    printf("a = %d ra = %d ra = %d\n",a,ra,rb);
    int&rbc = rb;
    printf("a = %d ra = %d ra = %d rbc = %d\n",a,ra,rb,rbc);
    return 0;
}
/*
sizeof(ra) = 4 sizeof(a) = 4
&a = 0061fea8 &ra = 0061fea8
a = 1000 ra = 1000
a = 1000 ra = 1000
*/

/*
a = 1000 ra = 1000 ra = 1000
a = 1000 ra = 1000 ra = 1000 rbc = 1000
*/

1 引用是一种声明关系,声明的时候必须要初始化,引用不开辟空间

2 此种申明关系,一经声明,不可变更

3 可以对引用再次引用,多次引用的结果是多个引用指向同一个变量

规则

1,引用没有定义,是一种关系型声明。声明它和原有某一变量(实体)的关系。故而类型与原类型保持一致,且不分配内存。与被引用的变量有相同的地址。

2,声明的时候必须初始化,一经声明,不可变更。

3,可对引用,再次引用。多次引用的结果,是某一变量具有多个别名。

4,&符号前有数据类型时,是引用。其它皆为取地址。

应用场景:

void swap(int *pa,int *pb)
{
    *pa ^= *pb;
    *pb ^= *pa;
    *pa ^= *pb;
}
void swap1(int &pa,int &pb)//利用引用传参,从c++的角度看没有开辟空间
{
    &pa ^= &pb;
    &pb ^= &pa;
    &pa ^= &pb;
}
int main()
{
    int a = 3;int b = 5;
    int c = 3;int d = 5;
    swap(a,b);
    cout<<"a = "<<a<<" b = "<<b<<endl;
    swap1(c,d);
    cout<<"c = "<<c<<" d = "<<d<<endl;
    return 0;
}
/*
a = 5 b = 3
c = 5 d = 3
*/

指针的引用

void swap(char **pa,char **pb)
{
    char *t = pa;
    *pa = *pb;
    *pb = t;
}
int main()
{
    char *pa = "chaina";
    char *pb = "america";
    cout<<"pa = "<<pa<<"pb = "<<pb<<endl;
    swap(pa,pb);//上述swap()函数中使用二级指针才可以实现交换。
    cout<<"pa = "<<pa<<"pb = "<<pb<<endl;
    return 0;
}
/*
pa = chainapb = america
pa = americapb = chaina
*/

指针的引用可以实现平级内的交换,不开辟空间

void swap(char* &pa,char* &pb)
{
    char *t = pa;
    pa = pb;
    pb = t;
}
int main()
{
    char *pa = "chaina";
    char *pb = "america";
    cout<<"pa = "<<pa<<"pb = "<<pb<<endl;
    swap(pa,pb);//上述swap()函数中使用二级指针才可以实现交换。
    cout<<"pa = "<<pa<<"pb = "<<pb<<endl;
    return 0;
}
/*
pa = chainapb = america
pa = americapb = chaina
*/

引用的本质是对指针的再次包装,指针是有引用的,不应该有引用的地址

引用的提高

引用的本质是指针,C++对裸露的内存地址(指针)作了一次包装。又取得的指针的优良特性。所以再对引用取地址,建立引用的指针没有意义。

1 可以定义指针的引用,但不能定义引用的引用

int *p;
int * & rp = p;//指针的引用

int a;
int & ra = a;
int & & raa = ra;//错误,没有引用的引用

2 可以定义指针的指针(二级指针),但不能定义引用的指针。

int **p;//二级指针
int a;
int &ra = a;
int & * p = &ra;//引用本身就是对指针的包装,再把引用打开包。与设计理念相悖。
//int * & ==>合法 指针的引用
//int & * ==>不合法 引用的指针

3,可以定义指针数组,但不能定义引用数组,可以定义数组引用。

int x,y,x;
int *p[] = {&x,&y,&z};//指针数组

int & rp[] = {x,y,x};//报错,引用数组,rp首元素,相当于int & *

int arr[] = {1,2,3,4,5};//int * 类型 对他引用就变成int * &,指针的引用
int * &rarr = arr;//报错,缺大小。
int (&rarr)[5] = arr;//right
int [5] &rarr = arr;//报错
int &rarr [5] = arr;//error,引用的数组

常引用

const 引用有较多使用。它可以防止对象的值被随意修改。因而具有一些特性。

(1)const 对象的引用必须是 const 的,将普通引用绑定到 const 对象是不合法的。这个原因比较简单。既然对象是 const 的,表示不能被修改,引用当然也不能修改,必须使用 const 引用。实际上,const int a=1; int &b=a;这种写法是不合法的,编译不过。

(2)const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初始化。这个是const 引用与普通引用最大的区别。const int &a=2;是合法的。double x=3.14; const int&b=a;也是合法的。

const不可以改,也不可通过指针或者引用去改变。

常引用原理:

const 引用的目的是,禁止通过修改引用值来改变被引用的对象。const 引用的初始化特性较为微妙

const int a = 100;//对a取地址是 const int *
int *p = &a;//c中可以,c++中不可
const int *p = &a;//C++

const int &ra = a;//必须添加const

int a;
double & ra = a;//报错,类型必须一致
const double & ra = a;//right

int y;
const int & ry = y;
int a = 200;
int & ra = a;
const double & rb = a;//他在底层用一个临时变量交换,double tmp = a;const double &rd = tmp;const修饰无法改变。
cout<<"a = "<<a<<endl;
cout<<"ra = "<<ra<<endl;
cout<<"rb = "<<rb<<endl;
a = 400;
cout<<"a = "<<a<<endl;
cout<<"ra = "<<ra<<endl;
cout<<"rb = "<<rb<<endl;

cout<<"&a = "<<&a<<endl;
cout<<"&ra = "<<&ra<<endl;
cout<<"&rb = "<<&rb<<endl;

/*
a = 200
ra = 200
rb = 200

a = 400
ra = 400
rb = 200

&a = 0x61fe8c
&ra = 0x61fe8c
&rb = 0x61fe90
*/

尽可能使用 const

use const whatever possible 原因如下:

1,使用 const 可以避免无意修改数据的编程错误。

2,使用 const 可以处理 const 和非 const 实参。否则将只能接受非 const 数据。

3,使用 const 引用,可使函数能够正确的生成并使用临时变量(如果实参与引用参数不匹配,就会生成临时变量)

引用和指针实质是一样的

原文地址:https://www.cnblogs.com/intelwisd/p/8506919.html

时间: 2024-10-29 19:07:52

C/C++(C++重载,默认参数,引用)的相关文章

C++函数:默认参数的函数

1.默认参数的目的 C++可以给函数定义默认参数值.通常,调用函数时,要为函数的每个参数给定对应的实参.例如: void delay(int loops); //函数声明 void delay(int loops) //函数定义 { if(100ps==0) return; for(int i=0;i<loops,i++); } 无论何时调用delay()函数,都必须给loops传一个值以确定时间.但有时需要用相同的实参反复调用delay()函数.C++可以给参数定义默认值.如果将delay(

Python:默认参数

Python是个人最喜欢的语言,刚开始接触Python时,总觉得有很多槽点,不太喜欢.后来,不知不觉中,就用的多了.习惯了.喜欢上了.Python的功能真的很强大,自己当初学习这门语言的时候,也记录过很多的笔记,现慢慢把这些笔记发布出来,希望对大家有所帮助,对自己也算是一个总结. 关于Python默认参数,假如默认参数是可变对象是会有副作用的,这一点我一开始不是很理解,直到有一天,看到一篇博文说:一个函数参数的默认值,仅仅在该函数定义的时候,被赋值一次.如此,只有当函数第一次被定义的时候,才讲参

在python函数中默认参数的一些坑

一.默认参数 python为了简化函数的调用,提供了默认参数机制: 这样在调用pow函数时,就可以省略最后一个参数不写: 在定义有默认参数的函数时,需要注意以下: 必选参数必须在前面,默认参数在后: 设置何种参数为默认参数?一般来说,将参数值变化小的设置为默认参数. python标准库实践 python内建函数: 函数签名可以看出,使用print('hello python')这样的简单调用的打印语句,实际上传入了许多默认值,默认参数使得函数的调用变得非常简单. 二.出错了的默认参数 引用一个官

&lt;C++&gt; 函数默认参数 函数重载 引用

一.函数默认参数 1.缺省参数:就是在声明函数的某个参数的时候 给他一个默认值 1 #include<iostream> 2 using namespace std; 3 4 void Show(int a = 1,int b = 2,int c = 3) 5 { 6 cout << a << endl; 7 cout << b << endl; 8 cout << c << endl; 9 } 10 11 int mai

重载函数和默认参数的函数

代码说事 重载的参数匹配 1 /// *重载的匹配顺序 1: 严格匹配 2: 转换匹配 2 /// *重申 : 重载的判断依据 !形参的! 个数 类型 位置 3 /// * 返回值类型不作为重载依据 4 /// * 默认参数 不能用于区分重载函数 5 6 #include <bits/stdc++.h> 7 using namespace std; 8 9 /// 转换 的匹配 10 double b; 11 void print(int a); 12 void print(char c);

函数重载和默认参数

区别一是参数类型不同,二是参数个数不同 仅有函数返回值不同也是区分不了重载函数的 1 #include <iostream> 2 using namespace std; 3 4 void go(int i, double db)//参数的个数,参数的类型不同,顺序不同,与返回值无关 5 { 6 7 } 8 9 void go(double db, int i) 10 { 11 12 } 13 14 void main() 15 { 16 17 system("pause"

默认参数与函数重载

一.默认参数在C++中,可以为参数指定默认值.在函数调用时没有指定与形参相对应的实参时, 就自动使用默认参数. 默认参数的语法与使用:(1)在函数声明或定义时,直接对参数赋值.这就是默认参数:(2)在函数调用时,省略部分或全部参数.这时可以用默认参数来代替. 注意:(1)默认参数只可在函数声明中设定一次.只有在无函数声明时,才可以在函数定义中设定.(2)默认参数定义的顺序为自右到左.即如果一个参数设定了缺省值时,其左边的参数都要有缺省值.如:int mal(int a, int b=3, int

【ThinkingInC++】38、选择重载还是默认参数

头文件 /** * 书本:[ThinkingInC++] * 功能:选择重载还是默认参数,头文件 * 时间:2014年9月6日14:54:28 * 作者:cutter_point */ #ifndef MEM_H_INCLUDED #define MEM_H_INCLUDED typedef unsigned char byte; class Mem { byte* mem; int size; void ensureMinSize(int minSize); //成员函数来增加内存块的大小 p

面向对象程序设计-C++_课时17函数重载和默认参数

函数重载,区别一是参数类型不同,二是参数个数不同. 默认参数可以多于1个,但必须放在参数序列的后部. 尽量不要用默认参数,会影响阅读 error C2668: “f”: 对重载函数的调用不明确 1 #include <iostream> 2 using namespace std; 3 4 void f(int i, int j = 0)//默认参数 5 { 6 std::cout << i << " " << j << st