一、代码
在正式阅读APM源码之前,了解C++的基础语法是必须的。以下抽取 AP_InertialSensor.h
文件的部分内容,以此说明C++基本语法。
class AP_InertialSensor : AP_AccelCal_Client
{
friend class AP_InertialSensor_Backend;
public:
AP_InertialSensor();
/* Do not allow copies */
AP_InertialSensor(const AP_InertialSensor &other) = delete;
AP_InertialSensor &operator=(const AP_InertialSensor&) = delete;
static AP_InertialSensor *get_singleton();
enum Gyro_Calibration_Timing {
GYRO_CAL_NEVER = 0,
GYRO_CAL_STARTUP_ONLY = 1
};
void init(uint16_t sample_rate_hz);
const Vector3f &get_gyro(uint8_t i) const { return _gyro[i]; }
const Vector3f &get_gyro(void) const { return get_gyro(_primary_gyro); }
Gyro_Calibration_Timing gyro_calibration_timing();
static const struct AP_Param::GroupInfo var_info[];
AuxiliaryBus *get_auxiliary_bus(int16_t backend_id, uint8_t instance);
class BatchSampler {
public:
...
private:
...
};
BatchSampler batchsampler{*this};
private:
void _start_backends();
static AP_InertialSensor *_singleton;
struct {
float delta_time;
} _hil {};
};
namespace AP {
AP_InertialSensor &ins();
};
以下分成几个小段,依次解释。
二、语法解释
class AP_InertialSensor : AP_AccelCal_Client
- 定义了一个类 AP_InertialSensor;
- 类
AP_InertialSensor
继承了AP_AccelCal_Client
,且是私有继承。
C++默认的继承为私有继承,如果是公有继承应改为class AP_InertialSensor : public AP_AccelCal_Client
;
也可以说,AP_AccelCal_Client
派生了一个类AP_InertialSensor
,AP_AccelCal_Client
叫做基类,AP_InertialSensor
叫做派生类。
派生类对象存储了基类的数据成员(派生类继承了基类的实现)
派生类对象可以使用基类的方法(派生类继承了基类的接口)
派生类需要自己的构造函数
派生类可以添加额外的数据成员和成员函数
派生类不能直接访问基类的私有成员,只能通过基类的方法进行访问
friend class AP_InertialSensor_Backend;
- 定义了类
AP_InertialSensor
的一个友元类AP_InertialSensor_Backend
。
友元类的成员函数可以访问原始类的私有成员和保护成员
public:
AP_InertialSensor();
/* Do not allow copies */
AP_InertialSensor(const AP_InertialSensor &other) = delete;
AP_InertialSensor &operator=(const AP_InertialSensor&) = delete;
- 定义默认构造函数
AP_InertialSensor()
,通过函数重载,定义另外两个非默认的构造函数。
构造函数是一种特殊的类成员函数,在创建类对象时被调用,构造函数没有类型声明
构造函数的名称与类名相同,但通过函数重载,可以创建多个同名的构造函数
如果只有默认构造函数,可省略。如果定义非默认的构造函数,则必须定义默认构造函数
通常,构造函数用于初始化类对象的成员,初始化应与构造函数的参数列表匹配
=delete
表示对于函数AP_InertialSensor(const AP_InertialSensor &other)
,传入参数时该函数被删除。换句话说,敲黑板强调了,不能使用AP_InertialSensor(const AP_InertialSensor &other)
这个函数。同理,后面一句是不允许使用=
对AP_InertialSensor
实例进行复制。
public:
static AP_InertialSensor *get_singleton();
private:
static AP_InertialSensor *_singleton;
- 定义一个 static类(静态类)成员函数
get_singleton()
,返回数据类型为AP_InertialSensor
类的指针。 - 定义一个指针类型的静态类成员
_singleton
。
静态类成员被所有对象共享,不会随着实例化新的对象而被复制
静态类成员须在类外初始化
静态成员函数属于类,不属于对象,是类域中的全局函数
静态成员函数被类、对象及类的派生类对象所共享
静态成员函数只能调用静态成员,不能调用非静态成员
void init(uint16_t sample_rate_hz);
- 一句很普通的函数声明
const Vector3f &get_gyro(uint8_t i) const { return _gyro[i]; }
- 声明一个叫做
get_gyro
的函数,返回是对类成员_gyro[i]
的引用。引用不会产生新的副本,也就是直接返回每个对象的_gyro[i]
,不会被复制。 - 后面的
const
说明该函数不可修改类成员_gyro[i]
的值,前面的const
说明返回值也是const
,即返回值也不可修改。简单说,这是一个“只读”函数。、 - 该函数还是一个隐式内联函数,也就是在类内定义,但没用
inline
显示声明。
enum Gyro_Calibration_Timing {
GYRO_CAL_NEVER = 0,
GYRO_CAL_STARTUP_ONLY = 1
};
Gyro_Calibration_Timing gyro_calibration_timing();
- 在类里定义了一个枚举类型
Gyro_Calibration_Timing
- 定义了一个返回类型为枚举变量的函数。实际上,返回值将是
GYRO_CAL_NEVER
或GYRO_CAL_STARTUP_ONLY
,也就是 0 或 1。
static const struct AP_Param::GroupInfo var_info[];
- 这里,
AP_Param
是一个类,GroupInfo
是一个结构体,定义了一个数组var_info
。这里并没有指明数组var_info
的长度,因此这是一个动态数组,也就是后面会使用new
和delete
来进行动态内存分配。静态数据需要指明数组长度。 - 返回类型中,
static
说明var_info
是一个静态成员,该类的所有实例共同拥有该变量,而不是每个对象复制一份。const
说明该类的每个对象都不可以修改var_info
的值。总结起来,var_info
是一个只能初始化一次而不可再被修改的全局变量。
AuxiliaryBus *get_auxiliary_bus(int16_t backend_id, uint8_t instance);
- 该函数返回一个指针变量。问题是什么时候使用指针什么时候使用引用?
参考链接:https://blog.csdn.net/hbtj_1216/article/details/56843014
如果数据对象是数组,则使用指向const的指针
如果数据对象是类对象,则使用const引用,传递类对象参数的标准方式是按引用传递
如果数据对象是较大的结构,则使用const指针或者const引用,以提高程序的效率
class BatchSampler {
public:
...
private:
...
};
BatchSampler batchsampler{*this};
- 在原来的类
AP_InertialSensor
中嵌套一个类BatchSampler
。 BatchSampler
实例化了一个对象batchsampler
,大括号和圆括号的意思是一样的,都是表示初始化。*this
表示传值,this
指向BatchSampler
的构造函数。
参考链接:https://bbs.csdn.net/topics/394335237
大括号是C++11后的统一初始化对象的一种方式,C++98年代是圆括号和大括号混用的,后来标准委员会的那帮大佬开会讨论后觉得这样不好,就统一都可以用大括号初始化了
private:
void _start_backends();
static AP_InertialSensor *_singleton;
struct {
float delta_time;
} _hil {};
private
表示成员及方法只能通过类AP_InertialSensor
的方法进行赋值与调用。
namespace AP {
AP_InertialSensor &ins();
}
- 自定义了一个命名空间,名叫
AP
。 AP_InertialSensor &ins();
不是很清楚,求高见!
参考链接:https://blog.csdn.net/weixin_43796685/article/details/101391950
用户或者C++本身定义了命名空间后,在该命名空间中也是一个独立的作用域,可以和其他作用域中存在相同名称的变量和函数。
— 完 —