学习自:太极创客。
实践是检验真理的唯一标准,通过arduino进行实践学习C++或许是一个不错的选择。

前篇回顾

  前篇学习了构造函数与析构函数,总体来说就是对象创建和消失时候要执行得函数。

前提知识

arduino中类库一般包含以下三部分:
一、src文件夹:
    .cpp文件(源文件):定义类库及其成员。
    .h文件(头文件):声明类库及其成员。
二、examples文件夹:
三、keywords.txt

创建.h文件和.cpp文件

  可发现随着功能不断的添加,程序代码变得越来越多,全部写在ino文件下,整个程序就显得异常的复杂,故可将部分程序移植到.h和.cpp文件中。

  在原工程的Led文件夹下,创建两个记事本,并分别命名并修改后缀为:Led.cpp和Led.h。得到以下:
在这里插入图片描述
  再打开Led.ino文件,可得到:
在这里插入图片描述

编辑Led.h文件

参考程序

#ifndef _LED_H_
#define _LED_H_
 
#include <Arduino.h>
 
class Led {
  public:
    Led();                    //析构函数
    Led(int userLedPin);      //重载析构函数(带参数)
    ~Led();
    void on();                //打开LED
    void off();               //关闭LED
    void setLedPin(int userLedPin);
    int getLedPin();
    
  private:
    int ledPin = 3;//初始化引脚编号为3(要与硬件搭建一致)
};//注意这边要有分号结束
 
#endif

程序详解

  #ifndef _LED_H_就是预编译 if no define _LED_H_即:如果没有定义 _LED_H_则执行下一句 #define _LED_H_
  总结:若没有定义 _LED_H _ 则定义 _LED_H _ 。若定义好了则什么都不执行。
  作用:该头文件经过这样设置后,若是有多个文件多次包含该头文件,也只会编译一次,即:若h文件中定义了全局变量,一个c文件包含一个h文件多次,可能造成变量定义重复错误,若添加该结构则不会出现这种错误(防止头文件被重复引用)。

    下面给一个#ifndef/#define/#endif的格式

     #ifndef A_H 意思是"if not define a.h" 如果不存在a.h

    接着的语句应该 #define A_H 就引入a.h

    最后一句应该写 #endif 否则不需要引入

  1、一般头文件只声明不定义的原因
    假如有一个头文件中有变量的定义,当这个头文件被多个.c文件包含的时候,在链接的时候就会在不同的编译单元导出符号表中查找出重复的定义,就会报错。
  2、类可以定义在头文件中的原因
    类的定义默认是static,内部链接,在其他的编译单元不可见,即使被重复包含。
  3、头文件(.h)都应该写些什么?
    写类的声明(包括类里面的成员和方法的声明)、函数原型、#define常数等,但一般来说不写出具体的实现。

编辑Led.cpp文件

参考程序

#include "Led.h"

Led::Led() {
  Serial.println("Led Object Created.");
  pinMode(ledPin, OUTPUT);
}

Led::Led(int userLedPin) {
  Serial.println("Led Object Created.");
  ledPin = userLedPin;
  pinMode(ledPin, OUTPUT);
}

Led::~Led(){
  Serial.println("Led Object Deleted.");
}

int Led::getLedPin() {
  return ledPin;
}

void Led::setLedPin(int userLedPin ) {
  ledPin = userLedPin;
  pinMode(ledPin, OUTPUT);      //设置为OUTPUT
}

void Led::on() {                //对ledPin输出高电平
  digitalWrite(ledPin, HIGH);
}

void Led::off() {               //对ledPin输出低电平
  digitalWrite(ledPin, LOW);
}

程序详解

  就是对头文件中已经声明的函数的具体实现,注意要包含对应的头文件。
  1、源文件(.cpp)都应该写些什么?
    源文件主要写实现头文件中已经声明的那些函数的具体代码。需要注意的是,开头必须#include一下实现的头文件,以及要用到的头文件。那么当你需要用到自己写的头文件中的类时,只需要#include进来就行了。

编辑Led.ino文件

参考程序

#include "Led.h"

void setup() {
  Serial.begin(9600);
  Led myLed;          //定义Led类对象myLed
  Led myLed2(5);      //定义Led类对象myLed2,且初始化ledPin为5.
  for (int i = 0; i < 5; i++) { //LED灯闪烁5次
    myLed.on();
    myLed2.on();
    delay(500);
    myLed.off();
    myLed2.off();
    delay(500);
  }
  Serial.print("int myLedPin =");
  Serial.println(myLed.getLedPin());
  Serial.print("int myLedPin2 =");
  Serial.println(myLed2.getLedPin());
}

void loop() {
  
}

程序详解

  首先要注意包含头文件。
  接下来就是通过引用头文件里面相关函数编写程序功能。

总结

  通过这种途径,将本来是一个很复杂的代码程序,我们分成了三部分,实际上它的好处还远远不止这个,如:
  ①分工明确。分成三文件,.h文件主要负责声明。.cpp主要负责具体的函数定义。.ino则是具体的实际应用。
  ②若别人想要使用你的类库,则只需要观察头文件中的声明而无需在意具体定义中的细节,从而实现简单的应用。
  ③若有场合不便公布源代码,则只需提供头文件和二进制库即可(不必关心接口怎么实现)。
  ④头文件能加强类型安全检查。若某接口被实现或被使用,其方式与头文件中的声明不一致,编译器则会指出错误。
  ⑤方便多人合作,若其他人合作一起完成,只需调用写好的库中某些函数,包含指定库即可,虽然可能造成很多无用声明。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐