Qt&;C++;:具有不同返回和参数类型的函数指针数组 我正在研究C++ 11,Qt 5.12。我需要在一些映射或数组中存储函数指针。关键是,这些方法有不同的返回类型和参数类型

Qt&;C++;:具有不同返回和参数类型的函数指针数组 我正在研究C++ 11,Qt 5.12。我需要在一些映射或数组中存储函数指针。关键是,这些方法有不同的返回类型和参数类型,c++,qt,callback,C++,Qt,Callback,我在类中定义了一些简单的数据结构。下面是一个尽可能简单的例子: class TableData { public: enum EnumFieldType { FieldType_None = 0, FieldType_Int, FieldType_QString }; enum EnumFieldId { FieldId_None = 0, FieldId_Id,

我在类中定义了一些简单的数据结构。下面是一个尽可能简单的例子:

class TableData
{
public:
    enum EnumFieldType
    {
        FieldType_None = 0,
        FieldType_Int,
        FieldType_QString
    };
    enum EnumFieldId
    {
        FieldId_None = 0,
        FieldId_Id,
        MaxSystemFieldId = 64
    };
int id() const;
void setId(const int _id);
QVariant getFieldValue(int _fieldId);
void setFieldValue(int _fieldId, QVariant _value)
protected:
int id_;
//Here some QMap or QVector with the function pointers
}

class EmployeeData : public TableData
{
public: 
    enum EnumFieldId
    {
        FieldId_Name = TableData::MaxSystemFieldId + 1,
        FieldId_Age
    };
   QString name() const;
   int age() const;
   void setName(const QString &_name);    
   int setAge(const Int &_age);    
protected:
    int             age_;
    QString         name_;
}
其想法是在TableData中创建三个映射:

  • QMap映射字段类型
  • QMap映射器
  • QMap
这些映射将在TableData子类构造函数中填充。因此,一旦构建了子类的实例,我可以使用:

EmployeeData  ed;
ed.setId(5);
ed.setAge(11);
ed.setName("Son Gohan");
或:

最后这些调用转到TableData::SetField方法,该方法应使用FieldId键查看map mapFieldTypes以获得字段的类型;然后获取setter函数指针并调用它,将QVariant参数正确转换为setter函数请求的类型

我花了很多时间在这个问题上挣扎,阅读,寻找和寻找一些解决方案。指针或回调数组必须具有相同的函数类型,std::function和std::bind不能解决这个问题(数组必须具有相同的函数类型,bind使用已经预定义的值,等等)。。。我需要类似于应用于变量的(void*)指针的东西,但对于函数指针(使用类型映射,我认为我可以有效地将通用函数指针转换为所需的函数指针模板)

有什么想法吗

PD:很抱歉出现了一些代码问题或拼写错误,真正的代码要复杂得多,我已经尽可能地简化和简化了它。

看起来是最适合您的解决方案:

class TableData : public QObject {
    Q_OBJECT

    public:
        TableData() : QObject(), _id(0) {}

        QVariant getFieldValue(const char * fieldName) const {
            return property(fieldName);
        }

        void setFieldValue(const char * fieldName, QVariant _value) {
            setProperty(fieldName, _value);
        }

        int id() const { return _id; }

        void setId(int newID) {
            _id = newID;
            emit idChanged();
        }

    protected:
        Q_PROPERTY(int id
                   READ id
                   WRITE setId
                   NOTIFY idChanged)
        int _id;

    signals:
        void idChanged();
};
void TableData::setField(const char*,QVariant)方法将调用
void QObject::setProperty(const char*,QVariant)。最后一个将自动调用您在
WRITE
属性字段中指定的setter,以更新属性值。以下三段代码的作用完全相同:

使用属性设置器:

EmployeeData ed;
ed.setId(5);
ed.setAge(11);
ed.setName("Son Gohan");
// Using the EmployeeData ed defined above
int id = ed.id();            // id == 5
int age = ed.age();          // age == 11
QString name = ed.name();    // name == "Son Gohan"
使用
void TableData::setField(const char*,QVariant)

使用
void QObject::setProperty(const char*,QVariant)(因为您的
EmployeeData
也是一个
QObject
):

读取属性也是如此。您的
QVariant TableData::getField(const char*)const方法将调用
qvariantqobject::property(constchar*)const。最后一个将自动调用您在
READ
属性字段中指定的getter以检索属性值。以下三段代码的作用完全相同:

使用属性设置器:

EmployeeData ed;
ed.setId(5);
ed.setAge(11);
ed.setName("Son Gohan");
// Using the EmployeeData ed defined above
int id = ed.id();            // id == 5
int age = ed.age();          // age == 11
QString name = ed.name();    // name == "Son Gohan"
使用
QVariant TableData::getField(const char*)const

EmployeeData ed;
ed.setField("id", 5);
ed.setField("age", 11);
ed.setField("name", "Son Gohan");
// Using the EmployeeData ed defined above
int id = ed.getField("id").toInt();               // id == 5
int age = ed.getField("age").toInt();             // age == 11
QString name = ed.getField("name").toString();    // name == "Son Gohan"
使用
qvariantqobject::property(constchar*)const(因为您的
EmployeeData
也是一个
QObject
):

看起来这是最适合您的解决方案:

class TableData : public QObject {
    Q_OBJECT

    public:
        TableData() : QObject(), _id(0) {}

        QVariant getFieldValue(const char * fieldName) const {
            return property(fieldName);
        }

        void setFieldValue(const char * fieldName, QVariant _value) {
            setProperty(fieldName, _value);
        }

        int id() const { return _id; }

        void setId(int newID) {
            _id = newID;
            emit idChanged();
        }

    protected:
        Q_PROPERTY(int id
                   READ id
                   WRITE setId
                   NOTIFY idChanged)
        int _id;

    signals:
        void idChanged();
};
void TableData::setField(const char*,QVariant)方法将调用
void QObject::setProperty(const char*,QVariant)。最后一个将自动调用您在
WRITE
属性字段中指定的setter,以更新属性值。以下三段代码的作用完全相同:

使用属性设置器:

EmployeeData ed;
ed.setId(5);
ed.setAge(11);
ed.setName("Son Gohan");
// Using the EmployeeData ed defined above
int id = ed.id();            // id == 5
int age = ed.age();          // age == 11
QString name = ed.name();    // name == "Son Gohan"
使用
void TableData::setField(const char*,QVariant)

使用
void QObject::setProperty(const char*,QVariant)(因为您的
EmployeeData
也是一个
QObject
):

读取属性也是如此。您的
QVariant TableData::getField(const char*)const方法将调用
qvariantqobject::property(constchar*)const。最后一个将自动调用您在
READ
属性字段中指定的getter以检索属性值。以下三段代码的作用完全相同:

使用属性设置器:

EmployeeData ed;
ed.setId(5);
ed.setAge(11);
ed.setName("Son Gohan");
// Using the EmployeeData ed defined above
int id = ed.id();            // id == 5
int age = ed.age();          // age == 11
QString name = ed.name();    // name == "Son Gohan"
使用
QVariant TableData::getField(const char*)const

EmployeeData ed;
ed.setField("id", 5);
ed.setField("age", 11);
ed.setField("name", "Son Gohan");
// Using the EmployeeData ed defined above
int id = ed.getField("id").toInt();               // id == 5
int age = ed.getField("age").toInt();             // age == 11
QString name = ed.getField("name").toString();    // name == "Son Gohan"
使用
qvariantqobject::property(constchar*)const(因为您的
EmployeeData
也是一个
QObject
):


是的,我认为这种方法适合我的需要。我想让TableData类尽可能简单,但这种方法和QObject+QProperty元系统的优点显然超过了缺点。我将重构我所有的数据结构。。。一堆工作,但我会值得的努力。谢谢PS:但我还是很好奇。。。?是否有可能获得具有不同返回值或参数的函数指针数组(或类似数组)?PS2:我喜欢你写例子时的谨慎。。。竖起大拇指如果您的类是从QObject派生的,那么您还可以使用Qt的自省API,以及元对象和
QMeta*
类。它可能不像您想要的那样是函数指针,但它仍然可以让您访问方法并调用它们。我想让TableData类尽可能简单,但这种方法和QObject+QProperty元系统的优点显然超过了缺点。我将重构我所有的数据结构。。。一堆工作,但我会值得的努力。谢谢PS:但我还是很好奇。。。?是否有可能获得具有不同返回值或参数的函数指针数组(或类似数组)?PS2:我喜欢你写例子时的谨慎。。。竖起大拇指如果您的类是从QObject派生的,那么您还可以使用Qt的自省API,以及元对象和
QMeta*
类。它可能不是您想要的函数指针,但它仍然允许您访问方法并调用它们。