【C++】四种类型转换 | C++异常处理机制 | C++11新特性之右值引用和移动构造

2023-05-16

文章目录

  • 一、C++中的四种类型转换
    • 1.1 静态类型转换
      • 1.1.1 C++中内置类型的转换
      • 1.1.2 C++中的有继承关系存在的场景下的类型强转
    • 1.2 动态类型转换
    • 1.3 常类型转换
    • 1.4 解释类型转换
  • 二、C++异常处理机制
    • 2.1 C中异常处理的缺陷
    • 2.2 C++中异常处理机制的套路
    • 2.3 C++中的标准异常库之常用异常类
    • 2.4 封装一个自定义异常类
  • 三、C++11新特性之右值引用
    • 3.1 右值引用的来源
    • 3.2 右值引用的语法形式
    • 3.3 右值引用与C++11中的新构造之移动构造

一、C++中的四种类型转换

1.1 静态类型转换

静态类型转换:static_cast<Type>(exp)
静态类型转换的两种应用场景:
1.C++中内置类型的转换。
2.C++中的有继承关系存在的场景下的类型强转。

1.1.1 C++中内置类型的转换

与C风格强转类似,但不能用于内置类型间的指针转换,因为每一种类型的指针代表他的操控的空间是不一样的。

代码示例:

#include <iostream>
using namespace std;

int main()
{
    double a = 3.1415926;
    cout << a << endl;
    cout << (int)a << endl;
    cout << static_cast<int>(a) << endl;
    cout << "-------------" <<endl;
    double *p=&a;
    cout << *p << endl;//3.14159
    cout << *((int*)p) << endl;//1293080650出错截断了,只取了前四位。
    //cout << static_cast<int>(p) << endl;报错
    return 0;
}

结果展示:
在这里插入图片描述
总结:
static_cast<int*>(pa)这种报错机制就是一种安全的体现,不允许对内置的指针类型进行转换。所以说static_cast比C风格强转要安全。

1.1.2 C++中的有继承关系存在的场景下的类型强转

如果使用static_cast由子类向父类转型,向上转型,天然安全。因为子类的实例中的类域就已经包括父类的类域空间。

如果使用static_cast由父类向子类转型(不安全的)。如果确认子类的空间已经成功开辟,那么则是安全的。如果不能确认子类的空间被开辟,由父类向下转型,则是不安全的。因为子类的指针可操控的空间大于已经合法定义的父类类间。

代码示例:

#include <iostream>
using namespace std;
class A
{
private:
    int a=100;
public:
    void show()
    {
        cout << "A的属性a:" << a << endl;
    }
};
class B:public A
{
private:
    int b=200;
    int c=300;
    int d=400;
    int e=600;
public:
    void show()
    {
        cout << "B的属性b:" << " b:" << b << " c:" << c << " d:" << d << " e:" << e <<endl;
    }
};

int main()
{
    //子类向父类转型天然且安全
    B b;
    static_cast<A>(b).show();
    ((A)b).show();
    A *p=new B;
    p->show();
    cout << "----------" << endl;
    //父类向子类转型非安全的
    A a;
    static_cast<B*>(&a)->show();//错误访问非法空间

    A *p2=new A;//向下转型不可以
    static_cast<B*>(p2)->show();//错误访问非法空间

    
    //安全情况
    A *p1=new B;//子类空间被开辟的情况下是安全的
    static_cast<B*>(p1)->show();
    
    B *p3=new B;//向上转型安全
    static_cast<A*>(p3)->show();
    return 0;
}

结果展示:
在这里插入图片描述
总结:
向上转型是安全的,向下转型如果不能保证子类空间被开辟则是不安全的。

1.2 动态类型转换

动态类型转换:dynamic_cast(Type*/Type&)(exp)只可以转指针或者引用。
动态类型转换是依赖于多态的实现的,也被称之为安全的转型,所以想使用它必须使用继承。
向下转型必须依赖多态中的虚表才能完成。
dynamic_cast他是依赖于虚函数背后的虚表中有第一个槽位置就存放了多态中的运行类型识别信息。
在这里插入图片描述
代码示例:

#include <iostream>
using namespace std;
class A
{
public:
    virtual void show()
    {
        cout << "正在学习C++" << endl;
    }
};
class B:public A
{
private:
    int b=200;
    int c=300;
    int d=400;
    int e=600;
public:
    void show()override
    {
        cout << "好好学习,天天向上" << endl;
    }
    void showB()
    {
        cout << "B的属性b:" << " b:" << b << " c:" << c << " d:" << d << " e:" << e <<endl;
    }
};

int main()
{
    //向上转型
    B b;
    dynamic_cast<A&>(b).show();
	//向下转型
	//A a;
    //static_cast<B*>(&a)->showB();//程序虽然还能执行,但是已经指向了非法空间,这种行为是不安全的
    //向下转型必须依赖于虚函数
    //dynamic_cast<B*>(&a)->showB();
    //没有虚函数不允许向下转型,有了虚函数后,如果子类空间没有被开辟,dynamic_case会返回一个空指针,
    //空指针调用函数,程序会直接终止,这是一种安全机制,所以向下转型推荐使用dynamic_cast
    //是虚函数作为背书的,转换的时候,dynamic首先会去虚表中看一下第一个槽的类型识别信息有没有你要转换的类型,
    //有可以转,没有则返回一个空指针
    A *p=new B;
    dynamic_cast<B*>(p)->showB();
    return 0;
}

结果展示:
在这里插入图片描述
总结:

  1. 向下转型static_cast<B*>(&a)->showB();程序虽然还能执行,但是已经指向了非法空间,这种行为是不安全的。
  2. 转换的时候,dynamic首先会去虚表中看一下第一个槽的类型识别信息有没有你要转换的类型,有可以转,没有则返回一个空指针。
  3. dynamic_cast<B*>(&a)->showB();没有虚函数不允许向下转型,有了虚函数后,如果子类空间没有被开辟,dynamic_case会返回一个空指针,空指针调用函数,程序会直接终止,这是一种安全机制,所以向下转型推荐使用dynamic_cast

1.3 常类型转换

常类型转换:const_cast<Type*/Type&>(exp)
C++所提供的这中常类型转换方式,只针对于常指针,或常引用进行转型。可读性更好。

代码示例:

#include <iostream>
using namespace std;

int main()
{
    int a=100;
    const int &b=a;
    cout << b << endl;
    (int&)b=1000;
    cout << b << endl;
    const_cast<int&>(b)=2000;
    cout << b << endl;

    const int *p=&a;
    //*p=3000;报错
    *(const_cast<int*>(p))=3000;
    cout << a << endl;
    return 0;
}

结果展示:
在这里插入图片描述

1.4 解释类型转换

解释类型转换:reinterpret_cast(Type)(exp)
转换风险最高一种转换方式,一般在公司开发中尽量避免。
底层实现:就是类型变量底层二进制代码的一种直接的拷贝。

代码示例:

#include <iostream>
using namespace std;

int main()
{
    int a=10;
    int *p=&a;
    //将地址转换为十进制打印出来
    cout << reinterpret_cast<long long>(p) << endl;
    cout << p+1 << endl;
    cout << reinterpret_cast<long long>(p)+1 << endl;
    return 0;
}

结果展示:
在这里插入图片描述

二、C++异常处理机制

2.1 C中异常处理的缺陷

代码示例:

#include <iostream>
using namespace std;
float my_div(int a,int b)
{
    if(b==0)
    {
        return -1;
    }
    return a/b;
}
float my_add(int a,int b)
{
    if(my_div(a,b)==-1)
    {
        return -1;
    }
    return my_div(a,b)+a+b;
}
int main()
{
    
    return 0;
}

通过代码我们可以发现c中的div由于可能导致的错误,使得每一个调用它的函数都要对它进行一次判断,十分冗余。并且当div中a=10,b=-10的时候,会得到-1,从而导致调用它的函数判断div出现了错误。

2.2 C++中异常处理机制的套路

为了应对C中处理的缺陷,C++有了自己独特的异常处理机制的套路。

1.throw关键字抛出异常。在有可能出现异常的函数内部使用throw来抛出异常。

throw + 常量 / 字符串 /自定义的类类型的对象。都可以做为throw抛出的异常。

2.使try{…}catch(表达式){…}来捕获异常,及处理异常。

try
{
    //把所有可能抛出异常函数全部放在try这个语句块中。
    //当函数中有异常被抛出时,那么这个函数将自动停止,
    //并跳转到catch语句块中进行下一步的处理。
}catch(exp用来接收异常对象){
    //处理异常的逻辑。
}
C++throw会在嵌套函数中层层抛出,如果外层没有使用try...catch...进行捕获
与处理,那么就会抛到main中,如果main也没有处理main函数将直接中止执行。

代码示例:

#include <iostream>
using namespace std;
float my_div(int a,int b)
{
    if(b==0)
    {
        throw -1;
    }
    if(b==-10)//随便设置看现象用
    {
        throw "随便设置看现象用";
    }
    return a/b;
}
float my_add(int a,int b)
{
    return my_div(a,b)+a;
}
int main()
{
    try {//放入可能会出现异常的函数
        cout << my_add(10,10) << endl;
        cout << my_add(10,-10) << endl;
        cout << my_add(10,0) << endl;//有异常直接跳转到catch
        cout << "异常" << endl;//有异常跳出try,这句代码没有执行
    } catch (int e) {//处理异常的逻辑
        if(e==-1)
        {
            cout << "除数不可以为零" << endl;
        }
    }catch (const char *err){
        cout << err << endl;
    }

    cout << "学习C++" << endl;//出现异常还可以继续向下执行
    return 0;
}

结果展示:
在这里插入图片描述
总结:

  1. try中出现异常语句会直接跳转到catch语句执行处理异常的逻辑。
  2. catch处理完异常会继续向下执行。
  3. try...catch...是做为一个整体出现的 不要分拆开。
  4. 不仅可以抛出数字,也可以抛出字符串。

2.3 C++中的标准异常库之常用异常类

在这里插入图片描述
返回的是字符串。
在这里插入图片描述
代码示例:

#include <iostream>
#include <exception>
using namespace std;
float my_div(int a,int b)
{
    if(b==0)
    {
        throw out_of_range("错误,除数不可以为0");
    }
    return a/b;
}
float my_add(int a,int b)
{
    return my_div(a,b)+a;
}
int main()
{
    try {//放入可能会出现异常的函数
        cout << my_add(10,10) << endl;
        cout << my_add(10,-10) << endl;
        cout << my_add(10,0) << endl;//有异常直接跳转到catch
        cout << "异常" << endl;//有异常跳出try,这句代码没有执行
    } catch (out_of_range& e) {//处理异常的逻辑,不知道多大用个引用
    		//引用栈上的一个临时空间
    		//这里没有使用右值引用是因系统会为异常对象开辟一块空间,
    		//来保存异常的这个结果对象。
            cout << e.what() << endl;//在catch语句块中处理异常的逻辑。
    }

    cout << "学习C++" << endl;//出现异常还可以继续向下执行
    return 0;
}

结果展示:
在这里插入图片描述

2.4 封装一个自定义异常类

#include <iostream>
#include <exception>
using namespace std;
//自定义异常类
class Error
{
private:
    string e;
public:
    Error(string e)
    {
        this->e=e;
    }
    string what()
    {
        return this->e;
    }
};

float my_div(int a,int b)
{
    if(b==0)
    {
        throw Error("错误,除数不可以为0");
    }
    return a/b;
}
float my_add(int a,int b)
{
    return my_div(a,b)+a;
}
int main()
{
    try {//放入可能会出现异常的函数
        cout << my_add(10,10) << endl;
        cout << my_add(10,-10) << endl;
        cout << my_add(10,0) << endl;//有异常直接跳转到catch
        cout << "异常" << endl;//有异常跳出try,这句代码没有执行
    } catch (Error& e) {//处理异常的逻辑
            cout << e.what() << endl;
    }

    cout << "学习C++" << endl;//出现异常还可以继续向下执行
    return 0;
}

结果展示:
在这里插入图片描述

三、C++11新特性之右值引用

3.1 右值引用的来源

在我们想了解右值引用有什么来源以及有什么作用时,首先我们应该掌握一个概念,什么是临时对象

简单来说,临时对象只会产生在栈上不会产生在堆上,在栈上只有空间,没有地址,下一行代码即马上销毁。
临时对象就是一个常量,也是一个右值。

但是在有属性指针指向堆区的情况下,临时对象就会造成计算性能的浪费。
使用const的左值引用来引用这个临时对象,但const修饰的左值引用又无法调用普通函数的情况下,C+11就引入了右值引用的新语法。

3.2 右值引用的语法形式

类型&& 变量 = 常量/临时对象。
右值引用,不能引用左值,只能引用右值。
如果想使用右值引用,引用一个左值,请使用移动语义函数std::move()

代码示例:

#include <iostream>
using namespace std;
class A
{
    int* p;
public:
    A()
    {
        this->p=new int[20];
        cout << "A的构造"  << endl;
    }
    virtual ~A()
    {
        delete [] p;
        cout << "A的析构" << endl;
    }
    A(const A& other)
    {
        this->p = new int[20];
        memmove(this->p,other.p,sizeof(int[20]));
        cout << "发生了拷贝构造" << endl;
    }
    virtual void showInfo()
    {
        cout << "学习C++" << endl;
    }
};
class B: public A
{
public:
    B()
    {
        cout << "B的构造" << endl;
    }
    ~B()
    {
        cout << "B的析构" << endl;
    }
    void showInfo()override
    {
        cout << "好好学习,天天向上" << endl;
    }
};
int main()
{
    A a = B();//临时对象,中间发生了拷贝构造,下一行销毁
    A a1 =A();//没有发送拷贝构造。编译器优化
    cout << "-------------------" << endl;
    const int& c = 100; //int temp = 10; const int& a = temp;
    const A& c1 = B();//A temp = B(); const A& c1 = temp;
    //c1.showInfo();//需要成员函数是常函数,可能遇到无法更改成员函数的情况
    const_cast<A&>(c1).showInfo();//可以解决也可以使用右值引用
    //右值引用:
    A&& c3 = B();
    c3.showInfo();
    //移动语义函数std::move(左值或右值)
    
    A&& c4 = std::move(c3);//相当于把c3这个左值强转成为了右值。
    c4.showInfo();
    cout << "-----------------------" << endl;
    return 0;
}

结果展示:
在这里插入图片描述

总结:

  1. 临时对象,只产生在栈上。只有空间,没有地址,所以他没有办法保存。临时的生命周期非常短暂,短到下一行代码执行时,他就销毁了。临时对象是一个常量,是一个右值。
  2. A a = B();临时对象,中间发生了拷贝构造,下一行销毁从。从结果我们可以发现,在下一行代码执行时就析构了
    A a1 =A();没有发送拷贝构造。编译器优化,下一行代码没有销毁。
  3. 我们不想临时对象刚产生就释放,所以可以const int& c = 100; //编译器底层实现int temp = 10; const int& a = temp;使用左值引用,引用右值。
  4. 因为const修饰,我们要使用常函数。可能遇到无法更改成员函数的情况
  5. 可以使用const_cast<A&>(c1).showInfo();或者右值引用来解决。
  6. 也可以使用右值引用去引用左值。移动语义函数std::move(左值或右值)
    相当于把左值强转成了右值。

3.3 右值引用与C++11中的新构造之移动构造

例如:购票系统,不想发生深拷贝,想使用浅拷贝提高性能。上一个人使用完了直接移给下一个人使用。
代码示例:

#include <iostream>
using namespace std;
class A
{
    int* p;
public:
    A()
    {
        this->p=new int[20];
        cout << "A的构造"  << endl;
    }
    virtual ~A()
    {
        if(p!=nullptr)
        {
            delete [] p;
        }
        cout << "A的析构" << endl;

    }
    A(const A& other)
    {
        this->p=new int[20];
        memmove(this->p,other.p,sizeof(int[20]));
        cout << "发生了拷贝构造" << endl;
    }
    //C++11的移动构造
    A(A&& other)
    {
        this->p=other.p;//浅拷贝
        other.p=nullptr;
        cout << "发生了移动构造" << endl;
    }
};
int main()
{
    A a;
    //A a1=a;隐式调用拷贝构造,发生深拷贝
    A a1=std::move(a);//强转成右值,在隐式调用了移动构造。
    return 0;
}

结果展示:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】四种类型转换 | C++异常处理机制 | C++11新特性之右值引用和移动构造 的相关文章

  • 【字符串函数】strcat的使用及原理

    1 strcat函数的函数声明 char strcat char Destination const char Source 2 strcat函数的头文件 include lt string h gt 3 strcat函数的使用 strca
  • 【DRM】DRM Display Driver Guide

    https zhuanlan zhihu com p 534267979 目录 收起
  • TCP协议

    1 TCP协议的可靠传输 我们知道TCP协议的特点有 有连接 可靠传输 面向字节流 全双工 其中连接 面向字节流和全双工在 网络编程 该文章中详细说明了 而要深入了解TCP协议 了解可靠传输也是重中之重 可靠传输也是TCP协议的一大特点 那
  • c/c++程序运行不出结果?

    1 xff0c 条件语句未执行 在运行过程中 xff0c 用到if或while等条件语句 xff0c 条件之后的语句没有执行就结束了 xff0c 且输出变量也未初始化 xff0c 当然就输出不了任何东西了 xff1b 2 xff0c 变量未
  • 【解救ROS】关于ros机器人(小车)动态调试PID参数

    1 打开终端 xff0c 连接树莓派 ssh clbrobot 64 clbrobt 2 打开底盘节点 roslaunch clbrobot bringup launch 3 再打开一个终端 ssh clbrobot 64 clbrobt
  • 十进制转十六进制(C语言)

    首先要注意输入非负整数的范围 xff1a 这里用long表示 xff1b long 取值 2147483648 2147483647 include lt stdio h gt int main long n int i 61 0 j ch
  • C语言之数组的定义及其使用方法

    作者 xff1a 从未止步 博客主页 xff1a 从未止步的博客 专栏 xff1a 和我一起学C 语录 xff1a Every day is a second chance 行动是理想最高贵的表达 xff0c 给大家介绍一款超牛的斩获大厂o
  • python之常量的定义

    常量 xff1a 与C语言不同的是 xff0c python中并没有用来修饰常量的修饰符 xff0c 在python中可以通过自定义实现常量 xff0c 要求常量的标识符必须全是大写字母 xff0c 且该值不能被修改 举例 xff1a PI
  • C语言之根据摄氏温度求华氏温度

    求摄氏温度26 C对应的华氏温度 计算公式 xff1a f 61 9 c 5 43 32 xff0c 式中 xff1a c表示摄氏温度 xff0c f表示华氏温度 输入输出示例 xff1a celsius 61 26 fahr 61 78
  • python文件的操作和异常之异常

    异常 xff1a python使用称为异常的特殊类对象来管理程序执行期间发生的错误 xff0c 每当发生让python不知所措的错误时 xff0c 他都会创建一个异常的对象 如果你编写了处理该异常的代码 xff0c 程序将继续进行 xff0
  • Java---抽象类和接口

    抽象类 xff1a 抽象类的基本概念 xff1a 在面向对象的概念中 xff0c 所有的对象都是通过类来描述并创建的 xff0c 但是有一种特殊的类 xff0c 并不能用完整的信息来描述一个具体的对象 xff0c 这样的类就是抽象类 xff
  • 通过基于注解的声明式事务实现事务功能~

    编程式事务 xff1a 事务功能的相关操作全部通过自己编写代码来实现 xff1a span class token class name Connection span conn span class token operator 61 s
  • 《DRM 专栏》| 彻底入门 DRM 驱动

    https cloud tencent com developer article 2021477 前面的 DRM 应用程序系列文章中 xff0c 我们学习了如何使用 libdrm 接口编写 DRM 应用程序 本篇我们将进入一个全新的世界
  • 声明式事务的属性~

    说明 xff1a 本篇文章的代码是基于上篇文章之上的 xff0c 如有需要 xff0c 请移至这篇文章 声明式事务的属性 xff1a 只读 xff0c 超时 xff0c 回滚策略 xff1a 事务属性 xff1a 只读 对一个查询操作来说
  • 配置SpringMVC的前端控制器DispatcherServlet时,<url-pattern>中“/“和“/*“的区别

    span class token comment lt 表示所匹配的请求可以是login或 html或 js或 css方式的请求路径 xff0c 但是 不能匹配 jsp请求路径的请求 xff0c 因此就可以避免在访问jsp页面时 xff0c
  • 解决在idea中构建项目出现不能创建java类,只能创建文件的问题~

    注意 xff1a 一定要根据箭头的指向顺序进行 修改完成 xff0c 如下所示 xff1a
  • 解决在idea中构建项目时,出现的java:错误:不支持发行版本 5

    错误描述 xff0c 如下所示 xff1a 错误原因 xff1a idea中默认配置中有几个地方的jdk版本与实际不一致 解决办法 xff1a 第一步 xff1a 第二步 xff1a 第三步 xff1a 第四步 xff1a 第五步 xff1
  • 【C++】搭建HTTP服务器

    目录 项目介绍 网络协议栈介绍 协议分层 数据的封装与分用 HTTP相关知识介绍 HTTP的特点 URL格式 URI URL URN HTTP的协议格式 HTTP的请求方法 HTTP的状态码 HTTP常见的Header CGI机制介绍 CG
  • vscode 出现“未定义标识符cout”

    1 检查是否有 xff1a include lt iostream gt using namespace std 2 若有 xff0c 可以修改一下vscode的设置 xff1a 将C Cpp intelli Sense Engine的 D
  • FreeRtos.STM32f103c8t6调用vTaskDelay时间不准问题

    1 选择晶振要选择正确 2 内核选择的主频要和实际一致 define configCPU CLOCK HZ unsigned long 72000000 系统主频 define configTICK RATE HZ TickType t 1

随机推荐

  • FreeRtos外部中断使用

    首先是config文件里的宏 ARM Cortex M 架构自身允许最多 256 个不同的优先级 xff08 最多有 8 个 优先级位 xff0c 因此从 0 到 0xff 的优先级都是可能的 xff09 xff0c 但绝大多数使用 ARM
  • MPU-6050资源介绍

    介绍 作用 xff1a 测量三轴加速度和三轴角速度 测三轴加速度 xff1a 加速度计 测三轴角速度 xff1a 陀螺仪 加速度计具有静态稳定性 xff0c 动态不稳定性 陀螺仪具有静态不稳定性 xff0c 动态稳定性 需要互补滤波 xff
  • STM32硬件I2C

    以I2C2为例子 硬件I2C不需要我们手动去翻转电平 首先配置I2C xff1a 配置GPIO xff0c 配置复用功能I2C 配置复用开漏 xff0c 使能I2C I2C起始条件函数 64 param I2Cx where x can b
  • 最简单的 DRM 应用 & drm设备不工作

    https zhuanlan zhihu com p 341895843 https zhuanlan zhihu com p 75321245 编写最简单的 DRM 应用 主程序 xff1a int main int argc char
  • spi通信

    特点 常规四线通信方式 一根片选线 xff0c 一根时钟线 xff0c 两根数据线 xff1a 一根是主进从出线 xff0c 一根主出从入线 同步 xff0c 全双工 xff0c 通信方式 和谁通信就将谁的片选线拉低 xff0c 每增加一个
  • FreeRtos任务通信之消息队列

    入队阻塞 xff1a 往队列写数据时 xff0c 队列满时的阻塞 当阻塞结束时 xff0c 优先级最高的任务优先进入就绪态 xff0c 同 优先级时 xff0c 阻塞时间最长的进入就绪态 出队阻塞 xff1a 读队列时 xff0c 队列为空
  • STM32F103C8T6 ADC功能

    12位逐次逼近型ADC 1us转换时间 输入电压0 3 3v和转化范围0 2 12 1 xff08 0 4095 xff09 成线性关系 2个ADC资源 xff0c ADC1和ADC2 xff0c 10个外部通道 有两种转换单元组 xff1
  • stm32串口实验

    目录 xff08 一 xff09 STM32 串口简介 二 软件设计 xff08 三 xff09 效果 xff1a 1 实现功能 xff1a STM32 通过串口和上位机的对话 xff0c STM32 在收到上位机发过来的字符串后 xff0
  • 基于stm32的GPS解析数据

    目录 1 GPS模块 2 GPS发送的数据格式 3 软件设计 3 1配置好串口 3 2然后写串口中断函数 效果 1 GPS模块 2 GPS发送的数据格式 GPRMC lt 1 gt lt 2 gt lt 3 gt lt 4 gt lt 5
  • 大疆遥控控制M3508电机二(基于HAL库)

    接上一篇文章 xff0c 话不多说直接开始 一 打开我们创建的工程文件 xff0c 先就建立一个文件夹用来存放我们写的子文件 xff08 不建立也行 xff09 xff0c 然后建立pid h xff0c pid c存入我们建立的文件夹中
  • aruco_ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法

    aruco ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法 运行环境问题描述解决方案 运行环境 系统版本 xff1a Ubuntu 16 04 ROS版本 xff1a Kinetic 问题描述 在进行手眼标定过程中 x
  • 安装vscode的时候没有勾选快捷方式用vscode打开文件,如何用vscode快速打开文件或者文件夹

    1 需要在注册表里面添加内容可以实现 xff0c 下面有一种简单的方式来完成这个操作 2 需要在电脑桌面新建一个Open File With VS code reg 文件然后用打开文件 xff0c 将以下代码复制 Windows Regis
  • C语言学习笔记->const和define区别

    1 define 是预编译指令 xff0c 而const 是普通变量的定义 define定义的宏是在预处理阶段展开的 xff0c 而const定义的只读变量在编译运行中使用 2 const定义的是变量 xff0c 而define定义的是常量
  • 基于栈、寄存器的优缺点

    基于栈的优点 xff1a 对硬件的依赖不高 xff0c 跨平台性 缺点 xff1a 使用的指令集高基于寄存器的优点 xff1a 相对于栈来说 xff0c 寄存器的性能高 xff0c 使用的指令集少 Java代码执行流程 xff1a java
  • Makefile文件的编写(实例详解)

    1 什么是Makefile xff1f 一个工程中的源文件不计其数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c Makefile定义了一系列的规则来指定哪些文件需要先编译 xff0c 哪些文件需要后编译 xff0c 哪
  • 用C语言实现万年历的代码及思路(详细教程)

    万年历程序要求 xff1a 1 当选择1的时候 xff0c 输入年 xff0c 打印输入的这一年12月的日历 2 当选择2的时候 xff0c 输入年 月 xff0c 打印输入这一年这一月的日历 实现效果 xff1a 选择1时 span cl
  • 有符号数和无符号数参与运算时的问题

    陷阱题目 xff1a 下面的代码输出是 xff08 xff09 span class token macro property span class token directive hash span span class token di
  • 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一 UDP的概念1 1 UDP1 2 UDP特点 二 采用UDP实现多人聊天室原因三 多人聊天室项目功能四 实现多人聊天室项目流程分析4 1 前期准备4 1 1 定义结构体4 1 2 定义链表 4 2 多人聊天室服务器4 2 1
  • 【C++】C向C++的知识过度(上)

    文章目录 一 C与C 43 43 的区别1 1 C是面向过程的1 2 C 43 43 是面向对象的1 3 编译器的区别 二 C与C 43 43 默认代码的不同三 命名空间3 1 关键字 96 namespace 96 去定义自己的名字空间
  • 【C++】四种类型转换 | C++异常处理机制 | C++11新特性之右值引用和移动构造

    文章目录 一 C 43 43 中的四种类型转换1 1 静态类型转换1 1 1 C 43 43 中内置类型的转换1 1 2 C 43 43 中的有继承关系存在的场景下的类型强转 1 2 动态类型转换1 3 常类型转换1 4 解释类型转换 二