无法理解这行C ++代码

时间:2016-08-08 21:35:06

标签: c++

我希望有人向我解释以下内容

我有C ++代码,在初始化期间包含这一行

ESPCommand<BufferedSerial> esp(D1, D0, PTC6);

其中ESPCommand是一个类,而BufferedSerial是一个类,这是我第一次看到这种类型的初始化是什么意思?这是课程

   class BufferedSerial : public RawSerial 
{
private:
    MyBuffer <char> _rxbuf;
    MyBuffer <char> _txbuf;
    uint32_t      _buf_size;
    uint32_t      _tx_multiple;

    void rxIrq(void);
    void txIrq(void);
    void prime(void);

public:
    /** Create a BufferedSerial port, connected to the specified transmit and receive pins
     *  @param tx Transmit pin
     *  @param rx Receive pin
     *  @param buf_size printf() buffer size
     *  @param tx_multiple amount of max printf() present in the internal ring buffer at one time
     *  @param name optional name
     *  @note Either tx or rx may be specified as NC if unused
     */
    BufferedSerial(PinName tx, PinName rx, uint32_t buf_size = 256, uint32_t tx_multiple = 4,const char* name=NULL);

    /** Destroy a BufferedSerial port
     */
    virtual ~BufferedSerial(void);

    /** Check on how many bytes are in the rx buffer
     *  @return 1 if something exists, 0 otherwise
     */
    virtual int readable(void);

    /** Check to see if the tx buffer has room
     *  @return 1 always has room and can overwrite previous content if too small / slow
     */
    virtual int writeable(void);

    /** Get a single byte from the BufferedSerial Port.
     *  Should check readable() before calling this.
     *  @return A byte that came in on the Serial Port
     */
    virtual int getc(void);

    /** Write a single byte to the BufferedSerial Port.
     *  @param c The byte to write to the Serial Port
     *  @return The byte that was written to the Serial Port Buffer
     */
    virtual int putc(int c);

    /** Write a string to the BufferedSerial Port. Must be NULL terminated
     *  @param s The string to write to the Serial Port
     *  @return The number of bytes written to the Serial Port Buffer
     */
    virtual int puts(const char *s);

    /** Write a formatted string to the BufferedSerial Port.
     *  @param format The string + format specifiers to write to the Serial Port
     *  @return The number of bytes written to the Serial Port Buffer
     */
    virtual int printf(const char* format, ...);

    /** Write data to the Buffered Serial Port
     *  @param s A pointer to data to send
     *  @param length The amount of data being pointed to
     *  @return The number of bytes written to the Serial Port Buffer
     */
    virtual ssize_t write(const void *s, std::size_t length);
};

这是另一个

template <typename SERIAL>
class ESPCommand {
private:
    SLIPPacket<SERIAL> _slip;
    DigitalIn _button;

public:
    ESPCommand(PinName tx, PinName rx, PinName button) : 
            _slip(tx, rx), _button(button){}

private:
    bool command_start(char cmd, uint16_t len) {
        len -= 4; // First word not included in length

        return _slip.req_start() &&
               _slip.putc(0x00) &&
               _slip.putc(cmd) &&
               _slip.send(&len, 2);
    }

    bool command_flush() {
        uint16_t len;

        return _slip.resp_start() &&
               _slip.getc() == 0x01 &&
               _slip.getc() >= 0 &&
               _slip.recv(&len, 2) &&
               _slip.recv(0, 4+len-2) &&
               _slip.getc() == 0x00 &&
               _slip.getc() >= 0 &&
               _slip.resp_finish();
    }

    bool command_finish() {
        return _slip.req_finish() && 
               command_flush();
    }

public:
    bool sync() {
#ifdef LED_STATUS
        led_green = 0; // Show progress
#endif
        while (true) {
            if (sync_frame()) {
#ifdef LED_STATUS
                led_green = 1; // Show progress
#endif
                return true;
            }
        }
    }

    bool sync_frame() {

        // Flush serial line
        _slip.flush();

        printf("\r\nPower cycle ESP, put into FW Update mode, push user button\r\n");
        int temp_button = _button;
        while( temp_button == _button){;} // wait for button press
        printf("\r\nContinuing Now\r\n");

        // Send sync frame
        uint32_t x = 0;

        if (!(command_start(ESP_SYNC_FRAME, 2*4 + 32) &&
              _slip.send(&x, 4) &&
              _slip.putc(0x07) &&
              _slip.putc(0x07) &&
              _slip.putc(0x12) &&
              _slip.putc(0x20)))
            return false;

        for (int i = 0; i < 32; i++) {
            if (!_slip.putc(0x55))
                return false;
        }

        if (!command_finish())
            return false;

        for (int i = 0; i < 7; i++) {
            if (!command_flush())
                return false;
        }

        return true;
    }

    bool flash_start(uint32_t blocks, uint32_t block_size, uint32_t address) {
        uint32_t x = 0;
        uint32_t size = blocks * block_size;

        return command_start(ESP_FLASH_START, 5*4) &&
               _slip.send(&x, 4) &&
               _slip.send(&size, 4) &&
               _slip.send(&blocks, 4) &&
               _slip.send(&block_size, 4) &&
               _slip.send(&address, 4) && 
               command_finish();
    }

    bool flash_data(const char *data, uint32_t len, uint32_t n) {
        uint32_t zero = 0;

        uint32_t x = 0xef;
        for (int i = 0; i < len; i++) {
            x ^= data[i];
        }

        return command_start(ESP_FLASH_DATA, 5*4 + len) &&
               _slip.send(&x, 4) &&
               _slip.send(&len, 4) &&
               _slip.send(&n, 4) &&
               _slip.send(&zero, 4) &&
               _slip.send(&zero, 4) &&
               _slip.send(data, len) &&
               command_finish();
    }

    bool flash_finish() {
        uint32_t x = 0;

        return command_start(ESP_FLASH_FINISH, 2*4) &&
               _slip.send(&x, 4) &&
               _slip.send(&x, 4) &&
               command_finish();
    }

    bool flash_write(uint32_t address, const char *data, uint32_t size) {
        uint32_t blocks = (size-1)/FLASH_BLOCK_SIZE + 1;

        printf("Synching...\r\n");
        if (!sync())
            error("Sync error!");

        printf("Starting transfer 0x%05x - 0x%05x\r\n", address, address + blocks*FLASH_BLOCK_SIZE);
        if (!flash_start(blocks, FLASH_BLOCK_SIZE, address))
            return false;

        for (int i = 0; i < blocks; i++) {
            printf("Flashing address 0x%05x\r\n", address + i*FLASH_BLOCK_SIZE);
            if (!flash_data(&data[i*FLASH_BLOCK_SIZE], FLASH_BLOCK_SIZE, i))
                return false;
        }

        printf("Finishing transfer\r\n");
        if (!flash_finish())
            return false;

        wait_ms(250);
        return true;
    }
};

3 个答案:

答案 0 :(得分:4)

它被称为模板类。基本上它在编译时根据一些参数创建一个类。

在这种情况下,BufferedSerialESPCommand<template T>模板类的参数。

您可以(并且应该)在每本C ++书籍或教程系列中阅读它。

答案 1 :(得分:2)

ESPCommand必须是模板类,BufferedSerial是它的参数。

简单示例:

vector<int> a(10);

这是标准库的矢量类。上面的行创建了一个int类型的向量,大小为10。

答案 2 :(得分:1)

ESPCommand是一个模板类。在ESPCommand<BufferedSerial>中,BufferedSerial是模板参数。模板有助于使用可以与不同模板参数重用的泛型类型/类。

例如,您可能需要编写一个存储int的数组类,然后编写一个存储float的数组类。为避免使用不同类型编写两次相同代码,您可以使用模板编写一次对任何给定类型有效的代码。这就是std :: vector或std :: list的作用。 C ++标准库中已经定义了很多模板类。

在你的情况下,ESPCommand似乎是一个已知命令发送到某个东西的类(这是一个调制解调器?),而BufferedSerial是知道如何与设备通信的类型。使用模板组装两者都会生成一种能够通过缓冲的串行线发送命令的类型(我猜)。如果通信层不同,您可以将模板参数更改为其他参数。