【问题标题】:Function pointer to class member generate compiler error指向类成员的函数指针生成编译器错误
【发布时间】:2018-02-09 06:28:52
【问题描述】:

亲爱的读者
我正在为进程调度程序制作一个库模块。默认调度程序有 8 个条目 0..7,调度程序中的函数/进程使用函数指针调用。编写为普通的 C 程序,它按预期工作。但是现在我想在 .h 文件中配置函数指针,我有指向函数指针的编译器错误。 我对位于 proclist[8] 中 &scheduler::dummy 的函数指针有疑问,它们会产生错误,我不知道如何解决它们。

谁能告诉我该怎么做。

产生的错误是

scheduler.cpp:9: In file included from

Error compiling libraries

scheduler.h: 56:87: error:
cannot convert 'void (scheduler::*)(uint8_t*) {aka void (scheduler::*)(unsigned char*)}' to 'void (*)(uint8_t*) {aka void (*)(unsigned char*)}' in initialization 
           { 7, 3900  ,10000 ,0,PROC_ACT ,&scheduler*: dummy7 , &proclist[7].val ,65  ,1}}; 
\\process table entry 7
Build failed for project 'Scheduler'

这个错误的 7 倍。

scheduler.h: 56:87: error: 
 cannot convert 'void (scheduler::*)(uint8_t*) {aka void (scheduler::*)(unsigned char*)}' to 'void (*)(uint8_t*) {aka void (*)(unsigned char*)}' in initialization

.h文件中的代码如下
(代码块中表示第 56 行)

 //process structure
typedef struct  process_t{                                  // Start of the Process scheduler structure
    uint8_t                         index               ;   // index of this process in the  process structure array
    uint32_t                        starttime           ;   // Absolute start and next call time of the function
    uint32_t                        delta               ;   // Time between the function to be called
    uint32_t                        exetime             ;   // Time it takes to execute the function
    uint8_t                         stat                ;   // skip, delete, change, active
    void                          (*pt2function)(uint8_t*) ;// Pointer to function to be called
    uint8_t                        *valptr              ;   // Pointer to value given as function Parameter
    uint8_t                         val                 ;   // Default value being pointed at
    uint8_t                         nextprocess         ;   // Index to next process in the process structure array
};

class scheduler {

    public:
            void    run();
            void    man  (uint8_t *); 
            void    dummy(uint8_t *);


        //  Processes 0,1..5 arrays of Process structs.
            process_t proclist[8]   =   {{0, ROLLOFFSET ,0     ,0,PROC_ACT ,&scheduler::man     , &proclist[0].val ,INIT    ,1} ,   //Initialise(), Run ones in the process list
                                        { 1, 3000       ,2237  ,0,PROC_ACT ,&scheduler::dummy   , &proclist[1].val ,65      ,2} ,   //process table entry 1
                                        { 2, 3100       ,2718  ,0,PROC_ACT ,&scheduler::dummy   , &proclist[2].val ,66      ,3} ,   //process table entry 2  
                                        { 3, 3200       ,3141  ,0,PROC_ACT ,&scheduler::dummy   , &proclist[3].val ,67      ,4} ,   //process table entry 3 
                                        { 4, 3300       ,2237  ,0,PROC_SKP ,&scheduler::dummy   , &proclist[4].val ,65      ,5} ,   //process table entry 4
                                        { 5, 3400       ,2718  ,0,PROC_SKP ,&scheduler::dummy   , &proclist[5].val ,66      ,6} ,   //process table entry 5
                                        { 6, 3500       ,3141  ,0,PROC_SKP ,&scheduler::dummy   , &proclist[6].val ,67      ,7} ,   //process table entry 6
/*===Line 56 ==>*/                      { 7, 3900       ,10000 ,0,PROC_ACT ,&scheduler::dummy   , &proclist[7].val ,65      ,1}};   //process table entry 7

            // and other functions if needed

    private:
            int8_t   n, cnt;
            uint32_t    mmillis();
};

【问题讨论】:

  • 指向成员函数的指针与指向非成员函数的指针不同。最大的区别是成员函数需要一个对象来调用,而非成员函数不需要。了解std::functionstd::bindlambda expressions
  • 这个错误告诉你你的函数签名是错误的以及它所期望的。 “(调度程序::)(uint8_t)”。之后调用该函数是另一回事,“一些程序员老兄”已经提供了答案。
  • 一种选择是制作scheduler::nanscheduler::dummy 静态成员函数(或全局函数)。如果这不可能,那么您必须按照上面 cmets 中描述的行重新设计您的代码。
  • 我试图修正你的格式。我不确定它是否和你的原版一模一样,但至少类型现在是可见的。

标签: c++ arrays class pointers


【解决方案1】:

非静态成员函数有一个指向类实例的隐藏指针this,因此Pointers to Member Functions 需要一个对象,您不能像普通函数指针那样使用它们。

根据您的设计,您可以互相交流

  1. 将方法设为静态:

    static void    man  (uint8_t *); 
    static void    dummy(uint8_t *);
    

    也许您必须再添加一个参数来传递对schedulerprocess_t 实例的引用。

  2. 或将pt2function更改为指向成员函数的指针:

    class scheduler;
    
    //process structure
    struct  process_t{                            // Start of the Process scheduler structure
        // ...
        void  (scheduler::*pt2function)(uint8_t*) ;// Pointer to function to be called
        // ...
    

    您以后可以像这样使用来自scheduler 的这些指向成员函数的指针

    class scheduler {
    // ...
    void run() {    
        (this->*proclist[0].pt2function)(proclist[0].valptr);
    }
    

Playground

【讨论】:

  • 我实施了第二个解决方案。它会生成一个错误,指出我如何从调度程序调用调度的函数/进程。在“C”中,我使用以下行: proclist[0].pt2function(proclist[0].valptr);那行得通。对于这个特定的行,我现在有以下错误 scheduler.cpp: 18:45: error: must use '.*' or '->*' to call pointer-to-member function in '((scheduler*)this)- >scheduler::proclist[0].scheduler::process_t::pt2function (...)',例如'(... ->* ((scheduler*)this)->scheduler::proclist[0].scheduler::process_t::pt2function) (...)。你能再次建议如何调用函数
【解决方案2】:

我实现了第二个解决方案,只要我在调度程序类中调用方法,它就可以工作。然而,调度程序将调用其他类的方法。下面的示例是我尝试调用一个名为“wifi_manager::statemachine”的方法,该方法管理 wifi 连接并每 1 秒调用一次。此指针分配失败,因为此状态机方法不是调度类的一部分,而是 wifi_manager 类的一部分。我需要做什么才能让我的 proclist[8] 包含指向各种类中各种方法的指针,这些方法由调度类中的方法“run”调用,以及如何调用这些函数/方法。

希望有人能帮我转发一下

/*
    scheduler.ino - tested at 7-2-2018
    Created by Oscar Goos, January 2018
    Test on Platform ESP8266-e12.
    Released into the public domain.
    Program size: 250,264 bytes (used 24% of a 1,044,464 byte maximum) (9.02 secs)
    Minimum Memory Usage: 32716 bytes (40% of a 81920 byte maximum) */

    #include "stdio.h"
    #include "scheduler.h"
    #include "wifi_manager.h"

    scheduler scul;

    void setup()
    {
        Serial.begin(115200, SERIAL_8N1);
        Serial.printf("\n");
        scul.proclist[1].pt2function=&wifi_manager::statemachine; // Assign pointer to proclist[1]
      /* add setup code here */
    }

    void loop()
    {
        scul.run();
      /* add main program code here */
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2017-07-27
    • 2013-06-06
    相关资源
    最近更新 更多