在构造函数初始化器列表中初始化函数指针数组 - 错误

Posted

技术标签:

【中文标题】在构造函数初始化器列表中初始化函数指针数组 - 错误【英文标题】:Initialize function pointer array in constructor initializer list - error 【发布时间】:2020-05-15 07:47:23 【问题描述】:

我正在尝试实现一个简单的菜单类,以便在编程 AVR 板时灵活使用。因此,我无法使用几个常用的 STL 文件(例如 functionalinitializer_list 等)。

我的菜单对象有指向前一个和下一个对象的指针,还有在某些情况下执行的函数指针。我对这些指针有疑问。

我设法用一个函数指针让一切工作。但是,当尝试使用函数指针数组时,我找不到初始化它的方法。请参阅下面或onlinegdb.com 上的最小示例。为简单起见,我将数组大小硬编码为 2。


错误信息

error: incompatible types in assignment of ‘void (**)()’ to ‘void (* [2])()’

为什么同一个语法tFcnPtr[2]会给出两种不同的类型??

构造函数参数变为void (**)(),而成员定义为void (* [2])()


函数指针类型定义

typedef void(*tFcnPtr)();

tMenu 类(效果很好!)

class tMenu   
  public:

    tMenu(tFcnPtr ptr) : _ptr(ptr) 

    void run() 
        _ptr();
    

    tFcnPtr _ptr;
;

tMenu2 类,不起作用。无法成功初始化函数指针数组。

class tMenu2 
  public:

    tMenu2(tFcnPtr ptrs[2]) : _ptrs(ptrs)  // error: incompatible types in assignment of ‘void (**)()’ to ‘void (* [2])()’

    void run() 
        for (auto& fcn : _ptrs) 
            if (fcn != nullptr) 
                fcn();
            
        
    

    tFcnPtr _ptrs[2];
;

测试

// Main test function
void p(const char c[]) 
    std::cout << c << std::endl;


// Main
int main()

    // Test functions
    tFcnPtr yup = []()p("Yup!");;
    tFcnPtr zup = []()p("Zup!");;
    tFcnPtr meh = []()p("Meh.");;

    // tMenu
    tMenu m1yup;
    m1.run();

    std::cout << std::endl;

    // tMenu2    
    tFcnPtr ptrs[] = zup, meh;
    tMenu2 m2ptrs;
    m2.run();

【问题讨论】:

C++中没有数组类型的函数参数。您可以这样编写它,但编译器会默默地将类型衰减为指针。这是 C 的继承,被 C++ 接管。您可以使数组成为引用类型,例如而不是int a[2](衰减到int *a)你可以写int (&amp;a)[2]。 (引用在 C 中不存在,而是在 C++ 中添加。)更方便和 C++-ish 将使用 std::array 代替。 关于参考的好提示,不知道它适用于函数和方法。很遗憾,我使用的编译器(avr-gcc/WIN-AVR)不支持she::array。 【参考方案1】:

其实function parameterptrs的类型不是array,而是pointer(即tFcnPtr *),不能用来直接初始化一个数组。这就是编译器所抱怨的。

参数列表中每个函数参数的类型根据以下规则确定:

2) 如果类型是“T的数组”或“T的未知边界数组”,则替换为“指向T的指针”类型

可以将数组成员初始化为

class tMenu2 
  public:

    tMenu2(tFcnPtr ptrs[2]) : _ptrsptrs[0], ptrs[1] 

    ...

    tFcnPtr _ptrs[2];
;

或者使用std::array(或std::vector,如果大小不固定)。

class tMenu2 
  public:

    tMenu2(std::array<tFcnPtr, 2> ptrs) : _ptrs(ptrs) 

    ...

    std::array<tFcnPtr, 2> _ptrs;
;

【讨论】:

哦,好吧。这是一个很好的解释。谢谢!我想要的是一种灵活的类型,它允许不同数量的指针。我认为不支持 std::array (我的编译器找不到 ),所以我想我必须创建自己的容器。没有大问题,但可能有问题? @Smartskaft2 std::array 从 C++11 开始支持,如果你不能使用它,我认为使用 std::vector 是一个好主意。 如果不支持std::array,我几乎不怀疑std::vector 支持。特别是因为动态内存在这些芯片上是一个很大的禁忌(没有太多可用的堆内存)。同样,这不是标准的 GCC 编译器。 avr-gcc 仅支持 C+11 的部分内容,对 STL 的支持不多。

以上是关于在构造函数初始化器列表中初始化函数指针数组 - 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在构造函数中使用删除器初始化 std::unique_ptr?

C++对象数组与对象指针

C++ 初始化器列表功能:调用函数而不初始化成员?

如何在构造函数中初始化指向字符串的指针数组[重复]

在构造函数的初始化列表中初始化数组

在构造函数初始化器中初始化成员数组