ardupilot中 C++多态(虚函数)学习

mac2022-06-30  61

目录

文章目录

目录摘要1.多态的定义2.虚函数3.纯虚函数4.ardupilot中虚函数定义4.ardupilot中纯虚函数定义

摘要

本节主要学习C++多态。 多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

1.多态的定义

C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。 下面的实例中,基类 Shape 被派生为两个类,如下所示:

//定义形状基类 #include <iostream> using namespace std; class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } int area() { cout << "Parent class area :" <<endl; return 0; } }; //定义正方形派生类 class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Rectangle class area :" <<endl; return (width * height); } }; //定义三角形派生类 class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Triangle class area :" <<endl; return (width * height / 2); } }; // 程序的主函数 int main( ) { Shape *shape; ///定义一个基类对象指针 Rectangle rec(10,7); //构造函数 Triangle tri(10,5); // 存储矩形的地址 shape = &rec; // 调用矩形的求面积函数 area shape->area(); // 存储三角形的地址 shape = &tri; // 调用三角形的求面积函数 area shape->area(); return 0; }

按照上面的代码我们希望输出不同子类的area,但是结果却是:

Parent class area Parent class area

导致错误输出的原因是,调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 area() 函数在程序编译期间就已经设置好了。 但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual,如下所示:

//修改基类的area函数为虚函数 class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } //声明为虚函数 virtual int area() { cout << "Parent class area :" <<endl; return 0; } };

上面运行结果:

Rectangle class area Triangle class area

此时,编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。

正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。


2.虚函数


虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。


3.纯虚函数

您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

我们可以把基类中的虚函数 area() 改写如下:

class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } // pure virtual function //定义纯虚函数,没有给出具体的实现过程 virtual int area() = 0; };

= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。

4.ardupilot中虚函数定义

// forward declare view class class AP_AHRS_View; class AP_AHRS { public: friend class AP_AHRS_View; // Constructor AP_AHRS() : _vehicle_class(AHRS_VEHICLE_UNKNOWN), _cos_roll(1.0f), _cos_pitch(1.0f), _cos_yaw(1.0f) { _singleton = this; // load default values from var_info table AP_Param::setup_object_defaults(this, var_info); // base the ki values by the sensors maximum drift // rate. _gyro_drift_limit = AP::ins().get_gyro_drift_rate(); // enable centrifugal correction by default _flags.correct_centrifugal = true; _last_trim = _trim.get(); _rotation_autopilot_body_to_vehicle_body.from_euler(_last_trim.x, _last_trim.y, 0.0f); _rotation_vehicle_body_to_autopilot_body = _rotation_autopilot_body_to_vehicle_body.transposed(); } // empty virtual destructor virtual ~AP_AHRS() {} // get singleton instance static AP_AHRS *get_singleton() { return _singleton; } // init sets up INS board orientation //定义一个虚函数,在基类中 virtual void init() { set_orientation(); }; private: static AP_AHRS *_singleton; };

4.ardupilot中纯虚函数定义

class AP_HAL::HAL { public: HAL(AP_HAL::UARTDriver* _uartA, // console AP_HAL::UARTDriver* _uartB, // 1st GPS AP_HAL::UARTDriver* _uartC, // telem1 AP_HAL::UARTDriver* _uartD, // telem2 AP_HAL::UARTDriver* _uartE, // 2nd GPS AP_HAL::UARTDriver* _uartF, // extra1 AP_HAL::UARTDriver* _uartG, // extra2 AP_HAL::I2CDeviceManager* _i2c_mgr, AP_HAL::SPIDeviceManager* _spi, AP_HAL::AnalogIn* _analogin, AP_HAL::Storage* _storage, AP_HAL::UARTDriver* _console, AP_HAL::GPIO* _gpio, AP_HAL::RCInput* _rcin, AP_HAL::RCOutput* _rcout, AP_HAL::Scheduler* _scheduler, AP_HAL::Util* _util, AP_HAL::OpticalFlow *_opticalflow, #if HAL_WITH_UAVCAN AP_HAL::CANManager* _can_mgr[MAX_NUMBER_OF_CAN_DRIVERS]) #else AP_HAL::CANManager** _can_mgr) #endif : uartA(_uartA), uartB(_uartB), uartC(_uartC), uartD(_uartD), uartE(_uartE), uartF(_uartF), uartG(_uartG), // uartH(_uartH), i2c_mgr(_i2c_mgr), spi(_spi), analogin(_analogin), storage(_storage), console(_console), gpio(_gpio), rcin(_rcin), rcout(_rcout), scheduler(_scheduler), util(_util), opticalflow(_opticalflow) { #if HAL_WITH_UAVCAN if (_can_mgr == nullptr) { for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++) can_mgr[i] = nullptr; } else { for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++) can_mgr[i] = _can_mgr[i]; } #endif AP_HAL::init(); } struct Callbacks { //定义纯虚函数 virtual void setup() = 0; virtual void loop() = 0; }; struct FunCallbacks : public Callbacks { FunCallbacks(void (*setup_fun)(void), void (*loop_fun)(void)); void setup() override { _setup(); } void loop() override { _loop(); } private: void (*_setup)(void); void (*_loop)(void); }; virtual void run(int argc, char * const argv[], Callbacks* callbacks) const = 0; AP_HAL::UARTDriver* uartA; AP_HAL::UARTDriver* uartB; AP_HAL::UARTDriver* uartC; AP_HAL::UARTDriver* uartD; AP_HAL::UARTDriver* uartE; AP_HAL::UARTDriver* uartF; AP_HAL::UARTDriver* uartG; //增加串口 AP_HAL::I2CDeviceManager* i2c_mgr; AP_HAL::SPIDeviceManager* spi; AP_HAL::AnalogIn* analogin; AP_HAL::Storage* storage; AP_HAL::UARTDriver* console; AP_HAL::GPIO* gpio; AP_HAL::RCInput* rcin; AP_HAL::RCOutput* rcout; AP_HAL::Scheduler* scheduler; AP_HAL::Util *util; AP_HAL::OpticalFlow *opticalflow; #if HAL_WITH_UAVCAN AP_HAL::CANManager* can_mgr[MAX_NUMBER_OF_CAN_DRIVERS]; #else AP_HAL::CANManager** can_mgr; #endif };
最新回复(0)