C 中的指针函数:从不兼容的指针类型初始化 foo

Pointer Functions in C: initialization of foo from incompatible pointer type

我正在使用 C,不允许使用 C++。目前,我正尝试在 C 中实现某种程度的 OOP。我目前正致力于实现多态性和继承。

我一天的大部分时间都在阅读如何通过使用函数指针来实现我的目标。我正在尝试打印两个结构的成员变量,如下所示:

RecordObject.h

typedef struct SuperRecordObject 
{
    char *Id;
    char *date;
    char *cases;
    char *deaths;
    void (*ptrPrintRecord)(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en);  
} SuperRecord;

typedef struct ChildRecordObject
{
    SuperRecord super;
    char *names_fr;
    char *names_en;
} ChildRecord;

我在这个文件中定义了函数ptrPrintRecord

RecordObject.c

#include <stdio.h>
#include "RecordObject.h"
void ptrPrintRecord(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en)
{
    //char *record;
    printf("     %s |   %s |            %s | %s |   %s |  %s\n", id, date, cases, deaths, names_fr, names_en);
    //return record;   
}

我尝试使用这个文件中的函数,例如:

DataLayer.c

#include <stdio.h>
#include <string.h>
#include "RecordObject.h"
/* more code here */

void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord; //
(*fun_ptr)(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);

/* more code here */

但是,当我编译(使用 GCC)时,我收到导致崩溃的警告。

warning: initialization of 'void (*)(char *, char *, char *, char *, char *, char *)' from incompatible pointer type 'void (**)(char *, char *, char *, char *, char *, char *)' [-Wincompatible-pointer-types]
   62 |        void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord;

我在其他文件中 运行 一些其他指针函数来搞乱和测试它,关于这里发生的事情我唯一能想到的是它可能与如何做有关字符串在 C 中有效吗?

您尝试的函数指针分配中有一个无关的 &。您的结构的 ptrPrintRecord 成员 已经是 正确类型的函数指针,因此您不需要 & - 这会给 那个指针的地址

只需使用:

void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; // No &

作为旁注,您使用 ptrPrintRecord 作为该成员(函数指针) 以及 作为实际函数的名称(具有相同的 'signature') 可能会导致一些问题,在未来的道路上。


此外,您需要将该成员(指针)实际初始化为一个有效的函数地址,然后再将其复制到您随后调用的对象(对于结构的其他成员也是如此)。这是一个小的 main(使用您的其他代码)可以工作:

int main()
{
    ChildRecord record;
    record.super.ptrPrintRecord = ptrPrintRecord; // See my note about the name clash!
    record.super.Id = "ID";
    record.super.date = "today";
    record.super.cases = "cases";
    record.super.deaths = "deaths";
    void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; //
    // To call the pointed-to function, we can just use the pointer name:
    fun_ptr(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);
    return 0;
}