自用的C++基础或进阶知识
用于复习C++的一些基本或者进阶操作,面向项目中可能用到但是不常注意到的知识点。
1. 主函数参数
入门C或者C++基础知识时,主函数都是直接用的下面形式:
#include<iostream>
using namespace std;
int main(){
cout<<"hello world"<<endl;
return 0;
}
而在C++标准中,其实main函数的主要形式有:
int main(void);
int main(int argc,char *argv[])// 等于 int main(int argc,char **argv);大概是SCI和SCI中的CCDC的关系
前者就是前面提到的形式,而后者在C++开发中更常用到,那后者main函数的argc和argv参数是什么意思呢?
这两个参数主要是用来保存程序运行时传递给main函数的命令行参数的。
- argc:是argument count 的缩写,保存运行时传递给main函数的参数个数。
- argv:是argument vector 的缩写,保存运行时传递main函数的参数,类型是一个字符指针数组,每个元素是一个字符指针,指向一个命令行参数。
argv[0]指向程序运行时的全路径名;
argv[1] 指向程序在命令行中执行程序名后的第一个字符串;
argv[2] 指向程序在命令行中执行程序名后的第二个字符串;
以此类推直到argv[argc]......
argv[argc] 在C++中指向nullptr,在C语言中指向NULL。
2.函数重载
函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。 在使用重载函数时,同名函数的功能应当相同或相近,不要用同一函数名去实现完全不相干的功能,虽然程序也能运行,但可读性不好,使人觉得莫名其妙。
注意,参数列表不同包括参数的个数不同、类型不同或顺序不同,仅仅参数名称不同是不可以的。函数返回值也不能作为重载的依据。
函数的重载的规则:
- 函数名称必须相同。
- 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
- 函数的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为函数的重载。
- C++代码在编译时会根据参数列表对函数进行重命名,例如
void Swap(int a, int b)会被重命名为_Swap_int_int,void Swap(float x, float y)会被重命名为_Swap_float_float。当发生函数调用时,编译器会根据传入的实参去逐个匹配,以选择对应的函数,如果匹配失败,编译器就会报错,这叫做重载决议(Overload Resolution)。
不同的编译器有不同的重命名方式,这里仅仅举例说明,实际情况可能并非如此。
从这个角度讲,函数重载仅仅是语法层面的,本质上它们还是不同的函数,占用不同的内存,入口地址也不一样。
3.C++句柄类详解
ROS中的ROS::NodeHandle nh 句柄用法
句柄可以让你通过构造函数指定命名空间
ros::init(argc, argv, "node_name");
(1)ros::NodeHandle nodel_handle;
ros::Publisher map_publisher_ = node_handle_.advertise<nav_msgs::OccupancyGrid>("map", 1, true);
上例子会发布节点<node_name>的话题/map
话题形式为:话题名字。
(2)ros::NodeHandle nodel_handle("~");
ros::Publisher map_publisher_ = node_handle_.advertise<nav_msgs::OccupancyGrid>("map", 1, true);
上例子会发布节点<node_name>的话题/node_name/map
(3)话题形式为:节点名字+话题名字。
NodeHandle类的主要成员函数:
(1)发布话题,返回一个Publisher,负责广播topic
Publisher advertise (const std::string &topic, uint32_t queue_size, bool latch=false)
(2)订阅一个话题,收到话题中的消息后触发回调函数
Subscriber subscribe (const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
从参数服务中获得某个参数
bool getParam (const std::string &key, std::string &s) const
附注:C++中的句柄用法
C++的句柄类handle()
引用来自百度百科的定义 句柄(handle)是C++程序设计中经常提及的一个术语。它并不是一种具体的、固定不变的数据类型或实体,而是代表了程序设计中的一个广义的概念。句柄一般是指获取另一个对象的方法——一个广义的指针,它的具体形式可能是一个整数、一个对象或就是一个真实的指针,而它的目的就是建立起与被访问对象之间的唯一的联系
句柄只能调用系统提供的服务,举个栗子,在ros操作系统中nh."-"这里只能调用系统已有的命名空间或是其他API。这在其他C++工程中同样适用,而指针是指向计算机虚拟内存的地址,而句柄更像是指向指针的索引值,大概是SCI和SCI中的CCDC的关系?就像是CCDC的JCR分区一直变化,而SCI索引一直就是那个索引。
句柄(稳定的)----->记载着对象在内存中的地址---->对象在内存中的地址(不稳定的)---->记载着实际对象的地址
4.Python与C++的异常处理
处理异常是每一个新手程序员的必备技能,但是如何处理异常却不是一件难事,对于日常码代码的各位很少有能养成习惯的,(ps:可能只有我QTQ )另外在构建大型工程如深度学习网络的代码时,也常常需要你构建如传参问题,数据处理格式方面的的异常提示,为后续良好的代码习惯打下基础。
(1)捕捉异常
捕捉异常可以使用try/except语句
try/except语句用来检测try语句块中的错误,从而让except捕获异常异常信息并处理
#!/usr/bin/python
#-*- coding:UTF-8 -*-
try:
fh = open("testfile","w")
fh.write("这是一个测试文件,用于测试异常!”) # 正常的操作
except IOError:
print "Error: 没有找到文件或读取文件失败" # 发生异常,执行这块代码
else:
print "内容写入文件成功"
fh.close() # 如果没有异常,执行这块代码
(2)触发异常
raise语句自己触发异常
def functionName( level ):
if level < 1:
raise Exception("Invalid level!", level)
# 触发异常后,后面的代码就不会再执行
5.C++异常处理
throw语句: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的
throw 表达式;
捕获异常 try catch语句
try {
语句组
}
catch(异常类型) {
异常处理代码
}
...
catch(异常类型/...) {
异常处理代码
//省略号代表抛出任何类型的异常
}
后续更新
学点C++系列
从零(接近0)开始SLAM系列
故障诊断与容错控制系列(不确定先立个flag)
如果考完试有时间我就写写最优化算法实现系列(我不会写的我只是想立个flag)