正确而简单地说应该使用静态类成员的指针而非指向类成员的指针
正如John_Lee所述的两个方法的分析,后者确实把简单问题复杂话了. 因为静态类成员是属于该类的全局对象和函数,它的指针是普通指针.引用该指针不需要类对象. 而类成员的指针必须总是通过特定的对象或指向该类类型的对象的指针来访问.
再者GCCAVR取FLASH数据必须通过pgm_read_word函数形成汇编代码LPM指令才能取出跳转地址. 而且将其转换为类成员的指针我和John_Lee一样都不能找到更好地方法,只能通过嵌入汇编语句完成. 这样也失去了C++的特色.
所以,静态类成员的指针应该是不错的方法.所以Key00()等函数必须声明为静态函数,这样才能在 KeyCommandTab[]函数指针数组中以函数名即函数的装载地址的身份出现,这样就实现了不同函数的散转.
至于函数指针数组是定义为静态类成员或在类成员函数中出现都无关紧要,但有一点是可以肯定的,那就是也必须 定义为静态数组,而且前者必须在类体外初始化,后者可以直接初始化. 特别注意后者虽可不定义为静态数组,但它 将会将数组装载在RAM中.例:
class KeyObj { public: KeyObj(void); void Exec(void);//每2.5mS中断调用一次, KeyCount会自动+1 private: void KeyInit(void); unsigned char GetKeyVal(void); void KeyCommandExec(unsigned char);//测试时需声明为public //................ static void Key00(void);//必须声明为static!!! //................ static void Key24(void);//必须声明为static!!! };//键盘模块
typedef void (* PFV)(void);//普通函数指针 void KeyObj::KeyCommandExec(unsigned char mode) { static PFV KeyCommandTab[3][5] PROGMEM = {//键盘放事件处理表//必须声明为static!!!否则忽略PROGMEM {Key00, Key01, Key02, Key03, Key04}, //键释放事件处理 {Key10, Key11, Key12, Key13, Key14}, //压键事件处理 {Key20, Key21, Key22, Key23, Key24} //长压键事件处理 }; PFV func;//定义普通函数指针 KeyCount &= 0x07;//取键盘序号//使用1602字节(.text),运行正确 if (KeyCount <= 4) {//只有5个键,KeyCount>=5为3个短接线. func = reinterpret_cast<PFV>(pgm_read_word(&KeyCommandTab[mode][KeyCount]));//取flash键盘放事件处理表 func();//运行KeyX0()~KeyX4() } }
最后感觉KeyCommandTab[]函数数组指针还是定义在类成员函数KeyCommandExec()为好,因为其他成员并不需要访问KeyCommandTab[]. 当然这样做会在不了解KeyCommandTab[]要取Key00()等函数指针时会把对Key00()等定义为静态函数产生疑问. 如果其他成员并需要访问KeyCommandTab[],则改为:
PFV func;//定义普通函数指针 class KeyObj { public: KeyObj(void); void Exec(void);//每2.5mS中断调用一次, KeyCount会自动+1 private: void KeyInit(void); unsigned char GetKeyVal(void); void KeyCommandExec(unsigned char);//测试时需声明为public //................ static const PFV KeyCommandTab[3][5];//必须声明为static!!! static void Key00(void);//必须声明为static!!! //................ static void Key24(void);//必须声明为static!!! };//键盘模块
//初始化键盘放事件处理表,因为KeyCommandTab数组为静态成员,故必须在类体外进行初始化 const PFV KeyObj::KeyCommandTab[3][5] PROGMEM = {//键盘放事件处理表 {Key00, Key01, Key02, Key03, Key04}, //键释放事件处理 {Key10, Key11, Key12, Key13, Key14}, //压键事件处理 {Key20, Key21, Key22, Key23, Key24} //长压键事件处理 };
void KeyObj::KeyCommandExec(unsigned char mode) { PFV func;//定义普通函数指针 KeyCount &= 0x07;//取键盘序号//使用1602字节(.text),运行正确 if (KeyCount <= 4) {//只有5个键,KeyCount>=5为3个短接线. //由于KeyCommandExec()函数也是KeyObj的类成员函数,故可直接访问KeyCommandTab[]数组 func = reinterpret_cast<PFV>(pgm_read_word(&KeyCommandTab[mode][KeyCount]));//取flash键盘放事件处理表 func();//运行KeyX0()~KeyX4() } }
现在和求助帖对比发现也就"static"一词之差,但结果却相差万里.
此帖到此讨论结束,也作为我对求助的总结"报告". 我认为求助而不总结的都是些"白帖",总结后就会知道自己永远还是一只不会飞的大菜鸟.
我很菜但我肯吃苦,我虽笨但我更努力. 我灌水但我不害人,我无翅但我梦飞翔.
再次感谢John_Lee和testcode两位网友!
|
|
文章评论(0条评论)
登录后参与讨论