2016-08-08 84 views
-4

我希望有人向我解釋以下無法理解這行代碼,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; 
    } 
}; 
+0

模板類?請查找。 –

+0

@πάνταῥεῖA *類模板*,即用於製作類的模板。 – juanchopanza

回答

1

ESPCommand是一個模板類。在ESPCommand<BufferedSerial>中,BufferedSerial是一個模板參數。模板有助於擁有泛型類型/類,它們可以與不同的模板參數一起使用。例如,您可能需要編寫一個存儲ints的數組類,然後存儲float的數組類。爲了避免兩次寫入不同類型的相同代碼,可以使用模板編寫一次代碼,該代碼對於任何給定類型都是有效的。這是std :: vector或std :: list的作用。在C++標準庫中已經定義了很多模板類。

在你的情況下,ESPCommand似乎是一個知道要發送命令的類(這是一個調制解調器?),而BufferedSerial是知道如何與設備通信的類型。使用模板進行組裝會生成一種能夠通過緩衝串行線發送命令的類型(我猜)。如果通信層不同,您可以將模板參數更改爲其他內容。

2

ESPCommand必須是一個模板類和BufferedSerial是它的參數。

簡單的例子:

vector<int> a(10); 

這是標準庫的向量類。上面的行創建了一個大小爲10的int類型的向量。

4

它被稱爲模板類。基本上它是在編譯時根據一些參數創建一個類。

在這種情況下,BufferedSerialESPCommand<template T>模板類的參數。

您可以(也應該)在每本C++書籍或教程系列中閱讀它。

+0

不幸的是,我從來沒有遇到過,我有模板變量的家庭,但不知道如何類可以成爲另一個類的模板,你能解釋更多 –

+0

就像上面提到的'vector '你可以做'vector ,它創建了一個新類「與class_you_wish一起工作的向量」 –