当前位置: 首页 > news >正文

域 缺省参数 函数重载 引用

一:域

C++库为了防止命名冲突,把自己库的东西都定义再std里。
局部变量:在栈存放
全局和静态变量:在静态区
常量:在常量区
动态分配:在堆
cout 是ostream类型的全局对象
cin 是istream类型的全局对象
endl 是个全局的换行符号
cout 和 cin 对比 c 的 printf 和 scanf 的优势是自动识别类型,原理是函数重载+运算符重载。

#include <iostream>
using namespace std; //整个展开std 但可能会导致命名冲突。(自己定义的东西和库中的命名冲突)// 部分展开,对常用的展开就不用加std了。
using std::cout;
using std::endl;int main()
{int a;cout << "hello world" << endl;cin >> a;return 0;
}

namespace定义的是域,本质解决c语言命名冲突问题。域不仅可以定义变量也可以定义函数。
命名冲突就是如下问题:有自己定义scanf后再使用scanf的库函数,就会冲突。

#include <stdio.h>
int main()
{int scanf = 10;scanf("%d", &scanf);return 0;
}

解决方法:

#include <iostream>
namespace na
{int scanf = 10;
}
int main()
{printf("%x", scanf);//指定访问命名空间中的printf("%x", na::scanf);return 0;
}
int a = 1;
int main()
{int a=10;printf("%d", a); //打印的是10,访问是局部优先printf("%d", ::a); // ::代表访问左边的域,左边是空白代表全局域。
}
struct Preson
{char name[10];int age;
};
int main()
{struct Preson p = {"校长", 10};printf("name: %s, age: %d\n", p.name, p.age);cout << "name: " << p.name << " " << "age: " << p.age << endl; return 0;
}

二:缺省参数

缺省参数:声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。调用变得更灵活。

void TestFunc(int a = 0)
{cout<<a<<endl;
}
int main()
{TestFunc();      // 没有传参时,使用参数的默认值 0TestFunc(10);   // 传参时,使用指定的实参 10
}

全缺省和半缺省:
1.半缺省参数必须从右往左依次来给出,不能间隔着给,就是说半缺省只能缺第一个(最左边的),对于下面的函数而言就是不能给a,b值而不给c值。
2. 缺省参数不能在函数声明和定义中同时出现
3. 缺省值必须是常量或者全局变量
4. C语言不支持(编译器不支持)

void TestFunc(int a = 10, int b = 20, int c = 30)
{cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;
}void TestFunc(int a, int b = 10, int c = 20)
{cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;
}

三:函数重载

函数重载:就是一词多义,c语言不允许定义同名的函数,但是c++可以。是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,(要求)这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。

要求:参数的 个数、类型、顺序不同。返回值不同无法构成重载。

int Add(int left, int right)
{return left+right;
}
char Add(char left, char right) // char也可以重载
{return left+right;
}
double Add(double left, double right)
{return left+right;
}void f(int a, int b, int c = 1) // 11
{
}
void f(int a, int b) // 22
{
}
int main()
{Add(10, 20); // 字面量 给的整形默认是常量Add('1', '2');Add(10.1, 20.2);// f是构成重载的,f(1,2,3) //调用 11f(1, 2)// 无法调用 因为不知道调用哪个。return 0;
}

1.为什么C不支持重载,C++支持?:函数名修饰规则。

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
f.h f.cpp main.cpp 三个文件
预处理:头文件展开 + 宏替换 + 去掉注释 + 条件编译 预处理后 f.h 和 f.cpp 生成 f.i ,f.h 和 main.cpp生成 main.i
编译:检查语法,生成汇编代码 生成 f.s 和 main.s 有了声名,main.i 函数就可以被放过去
汇编:将汇编代码转换为二进制的机器码 生成 f.0 和 main.o

  1. C语言在汇编阶段生成的 f.o 文件,会把同名函数不做区分,这样 main 就找不到想用的那个函数是哪个了。
  2. 而C++中会加入函数名修饰规则支持函数名重载。函数名修饰规则会把执行函数的名字前后加一些东西,eg:在 linux 下,如果是 add()函数,他会把函数名改成 _Z3addii,ii 代表的是如果 add 的两个参数是整形就是 ii ,如果 add 的参数是 double,就是在后面是 _Z3adddd,dd代表的是它的两个参数是 double。修饰规则是对所有函数都修饰,不止在同名函数才发生。

链接:链接到一起生成可执行程序 a.out

2.extern “c” 作用是什么?

有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译,不要用C++的规则修饰函数名去编译。
eg:tcmalloc是google用C++实现的一个项目,他提供tcmallc()和tcfree两个接口来使用,但如果是C项目就没办法使用,那么他就使用extern “C”来解决。
中间件程序 通常会把它编译成 静态库或者动态库。如果用C++写的程序提供接口函数给使用者,C++使用者可以直接使用,但如果是一个C使用者调用函数会找不到地址,因为在汇编过程中C使用不修饰的函数名找调用函数,而C++在汇编会产生修饰的函数名,因此无法调用。 如果在C++的程序函数前面加上 extern “C”,则就不会修饰,C可以直接调用。这时候如果用C++去调用的话,只需要加上extern “C” 就可以调用。加上extern "C"函数就不会重载了。

四:引用

当参数和返回值是比较大的变量时,传引用传参和传引用做返回值还可以提高效率。
只要符合条件,尽量使用引用传参,还可以防止深拷贝。
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。引用在定义时必须初始化, 一个变量可以有多个引用。权限可以缩小但不能放大。

int main()
{int a = 10;int x = 1;int& b = a; // b是a的别名(引用)就是重新给a这个地方起了一个新的叫法。int& r = a;r = x; // 这里是把x的值给r 也就是给a 不是让r这个引用引用到x上。const int a = 10;  // const变量是可以读,但不能写不能改不能修改。//int& ra = a;   // 该语句编译时会出错,a为常量。a是const 而ra是int的话类型就放大了可以修改,因此错const int& ra = a;// int& b = 10;  // 该语句编译时会出错,b为常量int b = 10;const int& rb = b;//可以 因为rb引用是权限的缩小,所以可以。int c = 10;double d = 1.11;//double&rc = c; // 不可以,因为c给rc引用会先产生一个double类型的临时变量值存放c,rc在引用这个临时变量,rc是这个临时变量的别名const double& rc = c; //可以,因为临时变量具有常性const int& b = 10; double d = 12.34;//int& rd = d;  // 该语句编译时会出错,类型不同const int& rd = d;
}

引用的作用: 引用在定义时必须初始化, 一个变量可以有多个引用。系统查越界基本是抽查,设置检查位查找你的读是否越界。

// 1.做参数
void swap(int& r1, int& r2)
{int tmp = r1;r1 = r2;r2 = tmp;
}
int main()
{int a = 1, b = 2;swap(a, b);return 0;
}// 2.做返回值
int add(int a, int b) // 传值返回 先把c给临时变量 相当于是返回的是c的拷贝
{int c = a + b;return c;
}//结合下面的使用,因此这块儿代码不能用引用返回,引用返回会导致返回临时空间的别名,函数结束返回值销毁返回这个位置的值
int& Add(int a, int b)// 传引用返回 返回对象c的引用
{int c = a + b;return c;
}
//这个可以使用引用返回,因为定义static是在静态区,出了函数(栈)后值还在
int& Add1(int a, int b)
{static int c = a + b;return c;
}
int main()
{int ret1 = add(1, 2); // 把临时变量给ret1const int& ret2 = add(1, 2); // 证明是临时变量而不是直接把C给ret2 因为int& ret2 = add(1,2)编译不过//ret的值不确定,因为c返回的c的引用,但函数结束Add函数结束了c的值没了,但空间在,这个空间的值无法确定int& ret = Add(1, 2);Add(3, 4);// 值是7 因为那块临时空间的值被覆盖了cout << "Add(1, 2) is :"<< ret <<endl; //Add(1, 2) is 7 这块儿相当于越界访问了。越界读可能不报错printf("hellow world");cout << "Add(1, 2) is :"<< ret <<endl; //纯随机值,因为printf使用空间后空间返回这块的值被修改return 0;
}

相关文章:

  • 【Golang】Go语言中如何面向对象?
  • 【研赛A题成品论文】24华为杯数学建模研赛A题成品论文+可运行代码丨免费分享
  • GO Serial 学习与使用
  • 大模型微调4:Alpaca模型微调、Adalora、Qlora
  • mysql学习教程,从入门到精通,SQL LIKE 运算符(28)
  • C++教程(三):c++常用的配置文件类型
  • 基于nodejs+vue的宠物医院管理系统
  • jupyter报错IProgress not found. Please update jupyter and ipywidgets
  • 基于Spring框架的分层解耦详解
  • 状态模式原理剖析
  • HTML基础用法介绍二
  • 计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-23
  • 单体到微服务架构服务演化过程
  • 《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析
  • Cocos 3.8.3 实现外描边效果(逃课玩法)
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • Bootstrap JS插件Alert源码分析
  • CSS实用技巧干货
  • CSS中外联样式表代表的含义
  • Effective Java 笔记(一)
  • ES10 特性的完整指南
  • Java程序员幽默爆笑锦集
  • LeetCode18.四数之和 JavaScript
  • leetcode-27. Remove Element
  • node入门
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • Ruby 2.x 源代码分析:扩展 概述
  • session共享问题解决方案
  • ubuntu 下nginx安装 并支持https协议
  • unity如何实现一个固定宽度的orthagraphic相机
  • vagrant 添加本地 box 安装 laravel homestead
  • vue--为什么data属性必须是一个函数
  • 关于extract.autodesk.io的一些说明
  • 开发基于以太坊智能合约的DApp
  • 前端面试之闭包
  • 前端学习笔记之观察者模式
  • 如何实现 font-size 的响应式
  • 如何学习JavaEE,项目又该如何做?
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 一份游戏开发学习路线
  • - 转 Ext2.0 form使用实例
  • ![CDATA[ ]] 是什么东东
  • #php的pecl工具#
  • $.ajax()参数及用法
  • $.proxy和$.extend
  • (12)Linux 常见的三种进程状态
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .Net Core中的内存缓存实现——Redis及MemoryCache(2个可选)方案的实现
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .NET和.COM和.CN域名区别