cpp_03_引用_类型转换_温和强转_面向对象

1  引用的应用

1.1  数据传递--值传递

        C语言只要涉及数据传递(例如:初始化、赋值、传参、返回值),

        都为值传递(将数据复制一份给到目标内存)。

// value.cpp 值传递:将数据复制一份给别人
#include <iostream>
using namespace std;

void foo( int x ) {  }

int bar( ) {
    int m = 8888;
    return m;
}

int main( void ) {
    int a = 10; // 初始化
    a = 20; // 赋值

    foo( a ); // 传参

    /*|8888|*/bar( ); // 返回值
    return 0;
}

        C++语言因为有引用,可以不做值传递。 

        1)引用型形参:函数的形参是实参的别名,避免对象复制的开销。

                非常引用型参数,可在函数中修改实参值;

                引用型参数,防止了对实参的意外修改,  也接受常量型实参(右值)。

// vparam.cpp 引用 作为函数的 形参
// 当我们在设计一个函数时,只要可以确定在函数内部绝对不修改实参,那么大胆的加上const
#include <iostream>
using namespace std;

void Swap( int* x, int* y ) { // 
    int z = *x;
    *x = *y;
    *y = z;
}

void Swap( int& x, int& y ) { // 非常引用型 形参:函数内部可以直接修改实参
    int z = x;
    x = y;
    y = z;
}
void Printer( const int& x, const int& y ) { // 常引用型 形参:能够防止意外修改实参
//  x = 888; // 编译器会提醒我们read-only  (打印机就应该原样打印哦)
    cout << x << ' ' << y << endl;
}

int main( void ) {
    int a=10, b=20;
    Swap( a, b );
//  Swap( &a, &b ); // 这种写法并不直观
    cout << "a=" << a << ", b=" << b << endl;

    Print( a, b );
    Print( 888, 999 ); //接受常亮型实参(右值)
    return 0;
}

         2)引用型的返回值:从函数中返回引用,一定要保证函数返回后,该引用的目标依然有效

                        -可以返回全局静态变量的引用

                        -可以返回在中动态创建(new)的对象的引用

                        -可以返回引用型参数本身

                        -可以返回成员变量的引用 

                        -可以返回调用对象自身的引用 

                        -不能返回局部变量的引用

               非常引用型返回值:通过引用可以修改目标

               引用型返回值:通过引用不能修改目标

// vreturn.cpp 引用 作为函数的 返回值
#include <iostream>
using namespace std;
int g_value = 0;
int& foo() { // 非常引用型 返回值:可以通过引用修改目标
    return g_value;
}
const int& fooo() { // 常引用型 返回值:不可以通过引用修改目标
    return g_value;
}

int& bar() {
    static int s_value=0;//这行代码是在程序启动时就执行,而且只执行1次,不是每次调bar都执行
    cout << "s_value=" << s_value << endl;
    return s_value;
}

int& hum() {
    int* p = new int;
    return *p;
}

int& fun( int& x ) {
    // ...
    return x; // 返回 引用型 参数本身
}
/*
int& boo() {
    int m = 666;
    return m; // 不要返回局部变量的引用
}
*/
int main( void ) {
    foo() = 100;
    cout << "g_value=" << g_value << endl;

//    fooo() = 888; // readonly - error

    bar() = 200;
    bar();

    hum() = 300;

    int a_value = 0;
    fun(a_value) = 400;
    cout << "a_value=" << a_value << endl;

//  boo();
    return 0;
}

        在实现(汇编)层面,引用就是指针,但在C++语言层面,引用不是实体类型,由此推导出,C++语言层面,引用与指针存在明显的差别:

        1)指针可以不初始化,其目标可在初始化后随意变更(指针常量除外),

              引用必须初始化,且一旦初始化就无法变更其目标。

        2)存在空指针,不存在空引用

        3)存在指向指针的指针,不存在引用的引用

        4)存在指针的引用,不存在引用的指针

        5)存在指针数组,不存在引用数组,但存在数组引用。

// poi_ref 指针 和 引用 的差别
#include <iostream>
using namespace std;

int main( void ) {
    int a=10, b=20;

    int* pa = &a; // 指针可以不做初始化,也可以做初始化
    pa = &b; // 指针可以随意变更它所指向的目标内存

    int& ra = a; // 引用必须初始化
    ra = b; // 引用不可以随意变更它所代表的目标内存( ra仍然是a的别名 )

    pa = NULL; // 存在空指针
//  ra = NULL; // 不存在空引用

    int** ppa = &pa; // 存在二级指针
//  int&& rra = ra;  // 不存在二级引用

    int* &rpa = pa; // 存在指针的引用  !!
//  int& *pra = &ra; // 不存在引用的指针
    int* p = &ra; // 这里取的并不是引用本身的地址,而是引用的目标内存a的地址

    int x, y, z;
    int*parr[3] = {&x, &y, &z}; // 存在指针的数组
//  int&rarr[3] = {x,y,z}; // 不存在引用的数组
    
    int arr[3];
    int(&rr)[3] = arr; // 存在数组的引用
    return 0;
}

 

2  显示类型转换(强转)

        C风格的显示类型转换:        (int)a 

        C++风格的显示类型转换:    int(a) 

// convert_pre.cpp 显式(强制)类型转换
#include <iostream>
using namespace std;

int main( void ) {
    int a;  double b;   float c;    short d;    char e;
    // 任何基本类型变量之间都可以 隐式转换
    a = b = c = d = e;
    e = d = c = b = a;
    // 任何其他类型的指针 到 void* 都可以隐式转换
    void* pv = &a;
    pv = &b;
    pv = &c;
    pv = &d;
    pv = &e;
    // void* 到 任何其他类型的指针 都必须强转(显式转换)
    int* pa = (int*)(pv);
    double* pb = (double*)(pv);
    float* pc = (float*)(pv);
    short* pd = (short*)(pv);
    char* pe = (char*)(pv);
    // 任何类型的 非常指针 到 同类型的常指针 都可以隐式转换
    const int* cpa = pa;
    const double* cpb = pb;
    const float* cpc = pc;
    const short* cpd = pd;
    const char* cpe = pe;
    // 任何类型的 常指针 到 同类型非常指针 都必须强转
    pa = (int*)(cpa);
    pb = (double*)(cpb);
    pc = (float*)(cpc);
    pd = (short*)(cpd);
    pe = (char*)(cpe);
    return 0;
}

3  温和强转

3.1  静态类型转换

                static_cast<目标类型>(源类型变量)

                隐式类型转换的逆转换(去常除外)

                自定义类型转换 

3.2  动态类型转换 

                dynamic_cast<目标类型>(源类型变量) 

                多态父子类指针或引用之间的转换 

3.3  常类型转换

                const_cast<目标类型>(源类型变量)

                去除指针或引用上的const属性

3.4  重解释类型转换

                reinterpret_cast<目标类型>(源类型变量)

                任意类型的指针之间的转换

                任意类型的引用之间的转换

                任意类型的指针和整型之间的转换

// convert.cpp 显式(强制)类型转换
#include <iostream>
using namespace std;

int main( void ) {
    int a;  double b;   float c;    short d;    char e;
    // 任何基本类型变量之间都可以 隐式转换
    a = b = c = d = e;
    e = d = c = b = a;
    // 任何其他类型的指针 到 void* 都可以隐式转换
    void* pv = &a; // int*->void*
    pv = &b;
    pv = &c;
    pv = &d;
    pv = &e;
    // void* 到 任何其他类型的指针 都必须强转(显式转换)*************
    int* pa = static_cast<int*>(pv); // void*->int*的反向int*->void*可以隐式
    double* pb = static_cast<double*>(pv);
    float* pc = static_cast<float*>(pv);
    short* pd = static_cast<short*>(pv);
    char* pe = static_cast<char*>(pv);
    // 任何类型的 非常指针 到 同类型的常指针 都可以隐式转换
    const int* cpa = pa; // int*-->const int*
    const double* cpb = pb;
    const float* cpc = pc;
    const short* cpd = pd;
    const char* cpe = pe;
    // 任何类型的 常指针 到 同类型非常指针 都必须强转***************
    pa = const_cast<int*>(cpa); // 去常属性
    pb = const_cast<double*>(cpb);
    pc = const_cast<float*>(cpc);
    pd = const_cast<short*>(cpd);
    pe = const_cast<char*>(cpe);
    // 除了void*外,其他任何类型的指针之间都必须强转*************
    pa = reinterpret_cast<int*>(pb); // double*-->int*
    pb = reinterpret_cast<double*>(1000); // int-->double*
    return 0;
}

 

4  面向对象

4.1  what

        一切皆对象。

        把大型软件看成是由多个对象组成的团推。

        对象拥有足够的智能,能够理解来自其他对象的信息,并以适当的行为作出反应。

        面向对象的三大特征:封装、继承、多态。

4.2  why

        相比分而治之的结构化程序设计,强调大处着眼的面向对象程序设计思想,更适合开发大型软件。

        得益于代码复用等面向对象的固有特征,软件开发的效率获得极大提升,成本却大幅降低。

4.3  how

        至少掌握一种面向对象的程序设计语言,如C++

        深入理解封装、继承、多态等面向对象的重要概念

        学习设计模式,源自多年成功经验的积累总结。

第三个错误:等号右边是右值,故等号左边应为万能引用int* const &r :

//test.cpp
#include <iostream>
using namespace std;


int main( void ) {
    int arr[9] = {9,3,1,4,2,7,5,8,6};

    int* p = arr;       // 正确  &arr[0]
    
    int(*pp)[9] = &arr; // 正确

//  int* &r = arr;      // 错误 &arr[0]     
    int* const& r = arr;// 正确

    int(&rr)[9] = arr;  // 正确
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/252694.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++软件调试与异常排查技术从入门到精通学习路线分享

目录 1、概述 2、全面了解引发C软件异常的常见原因 3、熟练掌握排查C软件异常的常见手段与方法 3.1、IDE调试 3.2、添加打印日志 3.3、分块注释代码 3.4、数据断点 3.5、历史版本比对法 3.6、Windbg静态分析与动态调试 3.7、使用IDA查看汇编代码 3.8、使用常用工具分…

正大杯获奖作品在哪可以看见

通过网盘分享的文件&#xff1a;2023年第十三届正大杯最新国家一等奖完整获奖作品报告等全套资料 链接:https://pan.baidu.com/s/1SPA4LumSCI4BZdCRXXnW6Q?pwdc8bj 提取码:c8bj 2023年第十三届最新正大杯国家一等奖完整获奖作品等全套资料获取方式链接https://ex59573j43x.fe…

造型精致的冰精灵充电头,充电效率高安全可靠,居家出行皆可用

随着大家对手机的依赖度越来越高&#xff0c;快速充电已经成为必不可少的需求。快充当然少不了支持快充的充电器&#xff0c;现在市面上的快充头很多&#xff0c;安全性和便携性是我们选择时的重点关注方向&#xff0c;我目前用的是战飞ZEFi冰精灵&#xff0c;这款产品有着独特…

〖大前端 - 基础入门三大核心之JS篇(56)〗- 内置构造函数

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;哈哥撩编程&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xff0c;目前在公司…

Python 全栈体系【四阶】(六)

第四章 机器学习 五、线性模型 1. 概述 线性模型是自然界最简单的模型之一&#xff0c;它描述了一个&#xff08;或多个&#xff09;自变量对另一个因变量的影响是呈简单的比例、线性关系。例如&#xff1a; 住房每平米单价为 1 万元&#xff0c;100 平米住房价格为 100 万…

Python学习路线 - Python语言基础入门 - 函数进阶

Python学习路线 - Python语言基础入门 - 函数进阶 函数的多返回值多个返回值 函数的多种参数使用形式函数参数种类位置参数关键字参数缺省参数不定长参数位置传递 - 不定长关键字传递 - 不定长 函数作为参数传递lambda匿名函数 函数的多返回值 问: 如果一个函数如些两个return…

java.net.SocketException: Connection reset

背景 在我用socket进行TCP通信的时候&#xff0c;当我关闭client端时在服务端出现了Connection reset的异常。 一、问题 下面是异常信息&#xff1a; Exception in thread "Thread-12" java.lang.RuntimeException: java.net.SocketException: Connection reseta…

基于ssm居家养老系统论文

居家养老系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了居家养老系统的开发全过程。通过分析高校学生综合素质评价管理方面的不足&#xff0c;创建了一个计算机管理居家养老系统的方案。文章介绍了居家…

数据手册Datasheet解读-MOS管笔记

数据手册Datasheet解读-MOS管笔记 NMOS应用场景一般特征第一个参数Vdss第二、三个参数Rds&#xff08;on&#xff09;、IdMOS管的散热绝对最大额定值第一个参数-Vd第二个参数-Vdgr第三个参数-Vg(栅源电压)第四个参数-Id第五个参数-Idm第六个参数-Ptot第七个参数-Viso第七和八的…

tomcat错误

Error running Tomcat8: Address localhost:1099 is already in use window环境&#xff0c;打开cmd netstat -ano | findstr :1099发现对应PID为24732 结束PID taskkill /PID 24732 /F

2023年度佳作:AIGC、AGI、GhatGPT、人工智能大语言模型的崛起与挑战

目录 前言 01 《ChatGPT 驱动软件开发》 内容简介 02 《ChatGPT原理与实战》 内容简介 03 《神经网络与深度学习》 04 《AIGC重塑教育》 内容简介 05 《通用人工智能》 目  录 前言 2023年是人工智能大语言模型大爆发的一年&#xff0c;一些概念和英文缩写也在这一…

字符迷宫(期末考模拟题)

很有趣的一道题 难点主要在于对于 * 的处理 题目描述的是可以多次匹配相同的字母&#xff0c;这就涉及到两个方面&#xff1a; 一是这个匹配的相同的字母如何储存 二是当你’ * ‘位置递归结束的时候&#xff0c;你该什么时候变回‘ * ’号 这里给出我的思路&#xff0c;如…

Zookeeper教程

Zookeeper教程 1、Zookeeper CLI ZooKeeper命令行界面CLI用于与ZooKeeper集合进行交互以进行开发。它有助于调试和解决不同的选项。 要执行ZooKeeper CLI操作&#xff0c;首先打开ZooKeeper服务器bin/zkServer.sh start&#xff0c;然后打开ZooKeeper客户端 bin/zkCli.sh。…

ActionCLIP:A New Paradigm for Video Action Recognition

文章目录 ActionCLIP: A New Paradigm for Video Action Recognition动机创新点相关工作方法多模态框架新范式预训练提示微调 实验实验细节消融实验关键代码 总结相关参考 ActionCLIP: A New Paradigm for Video Action Recognition 论文&#xff1a;https://arxiv.org/abs/21…

Kafka本地安装⭐️(Windows)并测试生产消息以及消费消息的可用性

2023.12.17 天气晴 温度较低 十点半&#xff0c;不是不想起实在是阳光浴太nice了日常三连&#xff0c;喂&#xff0c;刷&#xff0c;肝刷会儿博客&#xff0c;看会儿设计模式冷冷冷 进被窝 刷视频 睡觉看看kafka的本地部署 》》实践》》成功写会儿博客&#xff0c…

SLAM算法与工程实践——相机篇:传统相机使用(3)

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

C++ list常用操作

目录 一、介绍 二、list的常用操作 1、构造 2、迭代器 3、元素访问 4、容量操作 一、介绍 std::list文档链接 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个…

C语言学习NO.-操作符(二)二进制相关的操作符,原码、反码、补码是什么,左移右移操作符、按位与,按位或,按位异或,按位取反

一、操作符的分类 操作符的分类 算术操作符&#xff1a; 、- 、* 、/ 、%移位操作符: << >>位操作符: & | ^ 赋值操作符: 、 、 - 、 * 、 / 、% 、<< 、>> 、& 、| 、^单⽬操作符&#xff1a; &#xff01;、、–、&、*、、-、~ 、siz…

Android 架构 - MVVM

一、概念 概念基于观察者模式&#xff0c;数据的变化会自动更新到UI。通信 View→ViewModel&#xff1a;View作为观察者&#xff0c;监听ViewModel中数据&#xff08;LiveData、Flow&#xff09;的变化从而自动更新UI。 ViewModel→Model&#xff1a;ViewModel调用Model获取数据…

7.26 SpringBoot项目实战【还书】

文章目录 前言一、编写控制器二、编写服务层三、Git提交前言 本文是项目实战 业务接口 的最后一篇,上文 曾说过【还书】的 入口是【我的借阅记录】,因为【还书】是基于一次借阅记录而言,另外在4.2 数据库设计 曾分析过【还书】的业务场景,需要执行两步操作: 更新【借阅记…
最新文章