这是我写的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');
}
答案 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()); }
为避免奇怪而丑陋的语法,我建议使用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;
};