当与微控制器编程(Arduino)取得联系时,我看到以下类来控制特定引脚上的LED:
template <const uint8_t PIN>
class LED
{
public:
LED()
{
pinMode(PIN, OUTPUT);
}
void turnOn()
{
digitalWrite(PIN, HIGH);
}
void turnOff()
{
digitalWrite(PIN, LOW);
}
};
我可以通过
使用它LED<8> led;
led.turnOn();
点亮引脚8上的LED。
但我问自己: 为什么将引脚作为模板参数给出,为什么不作为实例属性?头等舱比这个好处有什么好处?
class LED
{
public:
LED(uint8_t ledPin) : pin(ledPin)
{
pinMode(pin, OUTPUT);
}
void turnOn()
{
digitalWrite(pin, HIGH);
}
void turnOff()
{
digitalWrite(pin, LOW);
}
private:
uint8_t pin;
};
并像这样使用它:
LED led(8);
led.turnOn();
在第二节使用第一节课是否有优势,或者仅仅是品味问题?:)
答案 0 :(得分:10)
“在第二节使用第一节课是否有优势,或者仅仅是品味问题?:)”
是。在模板的情况下,编译器可以直接使用数值而无需存储保存两个内存的变量(该数字必须存储在非模板情况下的RAM中)和电源(您需要将字节保存到的指令)存储器,然后加载到寄存器而不是直接加载到寄存器。)
在普通PC的情况下,保存都非常小,但实际上无关紧要,但是对于RAM较低(〜1MB以下)的小型设备(如微控制器)而言,每个字节都很慢。
但是,如果您将模板用于更多引脚(具有不同的编号),则您的应用程序将包含多种方法来打开和关闭(对于每个使用的引脚编号)增加可执行文件的大小。在这种情况下,您为应用程序节省了内存以节省数据和CPU功耗,然后它取决于您需要的更多 - 更小的应用程序,更大的内存和CPU功率开支,反之亦然。
答案 1 :(得分:4)
As noted by Laethnes,它可以帮助提高速度和内存消耗。不过,我还想提出一些更基本的内容:
模板参数强制在编译时做出决定。
这是一个关于您的代码以及如何使用它的非常强大的声明。在你的情况下,我认为它是合适的。
您的示例涉及具有LED附件的Arduino板。在任何合理的设置中,您都可以提前了解LED将要打开的数字引脚。如何设置硬件并不是程序运行时可能发生的变化。
使引脚成为模板参数是对该基本假设的严格执行;它使不可能因运行时决定影响LED的引脚号。如果它是一个普通的构造函数参数,你的类的用户可以在运行时进行一些计算,然后根据这些计算的结果确定LED在上的哪个引脚,在你的情况下,可能是不是一件有效的事。
当然,也许你真的做需要在运行时处理不断变化的硬件配置。如果是这样的话,模板参数只会妨碍你。但是,一般情况下,如果您可以进行编译时强制执行,那么您 的正确性是有利的。