C ++类中的返回函数指针

时间:2018-07-23 07:56:18

标签: c++

这是我写的C ++源代码。我想做的是运行init(),它是A类的成员函数,而get_func返回a(),b(),c(),d()中函数的地址。最后,执行了func(),我希望看到b。看起来很简单,但是现在这个问题困扰着我。

编译器给我以下错误: -在此范围内未声明“选择” -在此范围内未声明“ a” 返回(); -没有匹配的函数可以调用'A :: init(char)' a.init('b');

我想念什么?

#include <iostream>
class A {
private:
    int (A::*get_func())();
    int a(){printf("a");}
    int b(){printf("b");}
    int c(){printf("c");}
    int d(){printf("d");}

public:
    A();
    ~A();
    int init();
    char choice;
}

A::init(char ch) {
    this->choice = ch;
    int (A::*func)() = get_func();
    func();
}

int (A::*get_func())() {
    switch(choice) {
        case 'a' :
            return a;
        case 'b' :
            return b;
        case 'c' :
            return c;
        case 'd' :
            return d;
    }
}

int main() {
    A a;
    a.init('b');
}

3 个答案:

答案 0 :(得分:2)

这应该可以解决问题:

class A {
private:
    int a(){printf("a");}
    int b(){printf("b");}
    int c(){printf("c");}
    int d(){printf("d");}

public:
    using func = int (A::*)();
    A();
    ~A();
    char choice;

private:
    func foo();

};

A::func A::foo() {
    switch(choice) {
        case 'a' :
            return &A::a;
        case 'b' :
            return &A::b;
        case 'c' :
            return &A::c;
        case 'd' :
            return &A::d;
    }
}

而不是返回函数指针,而是在调用这些函数。 其次,我建议使用typedefs /与成员函数类型一起使用。  请注意,您没有在类定义的末尾添加分号。

答案 1 :(得分:1)

在编译后,您的代码中有几个错误:

try
        {

            ReportDocument r = new ReportDocument();               
            r.Load(path + rptname);


            CrystalDecisions.ReportAppServer.ClientDoc.ISCDReportClientDocument boReportClientDocument;
            CrystalDecisions.ReportAppServer.DataDefModel.Database boDatabase;
            CrystalDecisions.ReportAppServer.DataDefModel.Tables boTables;
            CrystalDecisions.ReportAppServer.Controllers.DatabaseController boDatabaseController;
            CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo boConnectionInfo;
            CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag boAttributesPropertyBag;
            CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag boLogonPropertyBag;

            boReportClientDocument = r.ReportClientDocument;
            boDatabaseController = boReportClientDocument.DatabaseController;
            boDatabase = boDatabaseController.Database;
            boTables = boDatabase.Tables;

            foreach (CrystalDecisions.ReportAppServer.DataDefModel.ISCRTable boTableOld in boTables)
            {

                CrystalDecisions.ReportAppServer.DataDefModel.ISCRTable boTableNew = boTableOld.Clone(true);
                boConnectionInfo = boTableNew.ConnectionInfo;
                boAttributesPropertyBag = (CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag)boConnectionInfo.Attributes;

                // Change the attributes and QE_LogonProperties to an ODBC connection
                boAttributesPropertyBag["QE_ServerDescription"] = dbpath;
                boLogonPropertyBag = (CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag)boAttributesPropertyBag["QE_LogonProperties"];
                boLogonPropertyBag["Data Source"] = dbpath;
                boLogonPropertyBag["Jet Database Password"] = "54321";
                boAttributesPropertyBag = (CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag)boConnectionInfo.Attributes;
                boTableNew.QualifiedName = boTableNew.Name;
                boTableNew.ConnectionInfo.UserName = "Admin";
                boTableNew.ConnectionInfo.Password = "";
                boDatabaseController.SetTableLocation(boTableOld, boTableNew);   
            }
            r.VerifyDatabase();
            crystalReportViewer1.ReportSource = r;
            crystalReportViewer1.Refresh();
        }
        catch (Exception ex) { MessageBox.Show(ex.ToString()); }

Demo

为避免奇怪而丑陋的语法,我建议使用typedef或拖尾返回类型

#include <iostream>
class A {
private:
    int (A::*get_func())();
    int a() {printf("a"); return 0;}
    int b() {printf("b"); return 0;}
    int c() {printf("c"); return 0;}
    int d() {printf("d"); return 0;}

public:
    A() = default;
    ~A() = default;
    void init(char);
    char choice;
};

void A::init(char ch) {
    this->choice = ch;
    int (A::*func)() = get_func();
    (this->*func)(); // ->* or .* is use to call member function
}

int (A::*A::get_func())() // You forget one `A::`, so define a free function.
{
    switch(choice) {
        case 'a' :
            return &A::a; // &A:: is require for pointer on member
                          // due to compatibility with C
                          // & is not required for address of free function :/
        case 'b' :
            return &A::b;
        case 'c' :
            return &A::c;
        case 'd' :
            return &A::d;
    }
    return nullptr;
}

int main() {
    A a;
    a.init('b');
}

并超出类定义

auto get_func() -> int (A::*)();

答案 2 :(得分:0)

如果您想尝试基于继承的方法:

class A {
public:
    A();
    ~A();
    virtual int init(){ printf("a"); }
};

class B : public A {
public:
    B();
    ~B();
    int init(){ printf("b"); }
};

class C : public A {
public:
    C();
    ~C();
    int init(){ printf("c"); }
};

class D : public A {
public:
    D();
    ~D();
    int init(){ printf("d"); }
};

如果您希望基类(A)是抽象的:

class A {
public:
    A();
    ~A();
    virtual int init() = 0;
};