基于构造函数的存在禁用代码

Disable code based on existence of Constructor

本文关键字:代码 存在 构造函数      更新时间:2023-10-16

我试图根据代码是否创建对象(或调用函数或其他什么(来禁用一些代码。听起来有点奇怪,我知道。

在我的库中,可以创建2个对象,每个对象都需要一个中断服务例程,如:

ISR(TIMER0_COMPA_vect) {
// do some stuff if the interrupt happens
}

ISR只能创建一次,但用户可能只创建了一个或没有创建我的对象,因此不应该首先创建ISR,以免阻止用户创建对象。我知道像这样封装代码会很容易

#ifdef OBJECT1
ISR(TIMER0_COMPA_vect) {
// do some stuff if the interrupt happens
}
#endif

但是这迫使用户保持对她/他创建的对象的跟踪。有没有一个选项可以让预处理器决定构造函数是否被调用过一次,甚至是否存在?有点像这个

Foo:Foo() {
#define USE_FOO
//Some code
}
#ifdef USE_FOO
ISR(TIMER0_COMPA_vect) {
// do some stuff if the interrupt happens
}
#endif

编辑:

根据我得到的答案,我试着澄清一下我的问题:

Foo1:Foo1() {
//Some object constructor code
}
Foo2:Foo2() {
//Some object constructor code
}
ISR(TIMER1_COMPA_vect) {
//some interrupt code
}
ISR(TIMER2_COMPA_vect) {
//some interrupt code
}
int main() {
Foo2 foo2;
}

如果这是我们正在讨论的代码,那么根本不应该编译函数ISR(TIMER1_COMPA_ect(。ISR必须缺席。

附言:如果你需要更多的信息,我可以提供更多,但我尽量保持问题的基本

对于这种情况,通常要做的是将此类对象的代码编译到库中。链接器足够智能,可以检测主程序是否依赖于库中的任何函数。如果是这样,它将把该函数的整个编译单元(即.c或.cpp文件(加载到程序中。它在编译单元中找到的任何ISR都将添加到您的程序中。如果不使用库中的任何函数,则不会添加ISR。

例如,在foo1.h:中放入这样的内容

#pragma once
class Foo1 {
public:
Foo1();
};

在foo1.cpp:中放入类似的内容

#include <foo1.h>
ISR(TIMER1_COMPA_vect) {
}
Foo1::Foo1() {
}

现在应该使用avr-gccfoo1.cpp编译为foo1.o。接下来,使用avr-arfoo1.o存储在名为foo1.a的归档中。然后,使用avr-gcc编译主程序,并提供foo1.a作为参数。确保foo1.a参数位于main.cpp之后。

您可能需要创建一个单例。有许多例子。singleton是一个只构造自己一次的类。构造函数是私有的,静态方法检查一个"全局"变量,看看类是否已经构造好了,如果没有,它只构造自己一次。您可能需要考虑线程问题,尽管对于构造,您可以在创建多个类之前尽早引用该类。对于中断的多个用户,通常使用对象注册的某种调度器,然后调用对中断感兴趣的所有类。调度器可以是单例。通常,调度器的客户端实现一个接口。作为向调度器注册的一部分,类告诉调度器它的"this"指针,调度器可以调用从接口实现的方法,就像它们被正常调用一样。客户端不需要有静态方法。这种东西可能有一些模式,但我无法说出任何模式。

正如你所说,你的问题听起来很奇怪,但如果你只想做一次,比如说在构造函数中,你可以使用局部静态变量来处理一个简单但非常丑陋的事情

Foo:Foo() {
static bool init = true;
if( init ) {
//Some code for ISR init
init = false;
}
}

这样,您的特殊ISR初始化将只发生一次,无论您或您的用户构建的Foo对象的数量如何

编辑:

我认为没有办法实现你想要的,至少没有干净的方法。

我认为你的问题来自你的ISR宏,它实际上做了两件事:

  • 初始化ISR矢量(ISR注册(
  • 定义您的ISR处理程序(ISR处理程序(

为了解决您的问题,我建议您将其拆分为两个宏,然后:

  • ISR注册进入Foo1/Foo2构造函数->使用全局字段或任何机制只初始化一次或在内部跟踪发生的事情
  • 保留另一个仅包含处理程序定义的宏ISR_HANDLER

然后,您的处理程序可以保持定义状态,如果它没有被任何Foo类注册,则不应该有任何影响