我有两个类用来表示一些硬件:一个 Button 类和一个 InputPin 类,它们表示一个按钮,当它被按下时会改变 IC 输入引脚的值。它们的一个简单示例是:
template <int pinNumber> class InputPin
{
static bool IsHigh()
{
return ( (*portAddress) & (1<<pinNumber) );
}
};
template <typename InputPin> class Button
{
static bool IsPressed()
{
return !InputPin::IsHigh();
}
};
通过使用类模板,这工作得很好,下面的条件将像我在汇编中手写它一样紧密地编译(一条指令)。
Button < InputPin<1> > powerButton;
if (powerButton.IsPressed())
........;
但是,我正在扩展它以处理中断并且遇到循环引用问题。
与原来的InputPin相比,新的InputPinIRQ类多了一个静态成员函数,当引脚值改变时,硬件会自动调用该成员函数。我希望它能够通知 Button 类,以便 Button 类可以通知主应用程序它已被按下/释放。我目前通过将指针传递给回调函数来做到这一点。为了让编译器内联回调代码,我认为需要将这些函数指针作为模板参数传递。所以现在,这两个新类都有一个额外的模板参数,它是一个指向回调函数的指针。不幸的是,这给了我一个循环引用,因为要实例化一个 ButtonIRQ 类,我现在必须做这样的事情:
ButtonIRQ<InputPinIRQ<1, ButtonIRQ< Inp.... >::OnPinChange>, OnButtonChange> pB;
其中......代表循环引用。
有谁知道如何避免这种循环引用?我是模板的新手,所以可能遗漏了一些非常简单的东西。
附言。重要的是,编译器确切地知道中断发生时将运行什么代码,因为它随后会进行一些非常有用的优化——它能够内联回调函数,并将回调函数的代码直接插入到 h/上调用的确切地址w 中断。
最佳答案
我会更改设计,使按钮与输入引脚相关联:
class Button
{
boost::smart_ptr<InputPin> p_input_pin;
}
或者更改 pin 类,使其具有订阅者列表。这可能是更好的设计,因为它允许在 pin 更改其值时通知许多订阅者。您还可以添加一个方法 (setter) 来设置引脚的值。
用例 1:按下按钮。
按下按钮更改输入引脚的状态。
输入 pin 通知订阅者事件。
用例 2:中断。
中断 {object} 改变输入引脚的状态。
输入 pin 通知订阅者事件。
订阅者/发布者设计模式非常适合这些用例。
关于c++ - 类模板实例化 : any way round this circular reference?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3048107/