- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有 2 个 C++ 类问题:
第一个问题是:我怎样才能做到这一点,以便我可以将类成员函数作为参数传递给另一个函数,然后我怎样才能运行/调用该函数?我怎样才能对类静态函数做同样的事情。通过查看这段代码可能更容易理解我的问题:
class DebuggingManager
{
string testLog;
bool test1()
{
// run test & return whether it passed or failed
}
static bool test2()
{
}
// How can I call a member function?
void catalogueTest( string testName, bool DebuggingManager::*nMemberFunction )
{
testLog += "Status of " + testName + ": " + ((*)nMemberFunction()) + "\n";
}
// How can I call a static function?
void catalogueTest( string testName, bool DebuggingManager::*nStaticFunction )
{
testLog += "Status of " + testName + ": " + DebuggingManager::nStaticFunction() + "\n";
}
// how do I pass a member function or a static function as a parameter in another function
bool runTests()
{
catalogueTest( "Test of member functin", test1() );
catalogueTest( "Test of static functin", test2() );
}
};
第二个问题是:像上面那样间接调用类成员(或静态)函数是不好的(或危险的)做法吗?我有一种感觉,这真的是糟糕的 C++ 实践?
编辑:实现建议感谢您的回复,我已尝试实现该建议,但它让我头疼不已,这是正确的吗?
// I have a feeling that ParameterList is incorect, would I pass the implicit obj as a parameter or is it done automatically like in normal object function calls?
typedef bool (DebuggingManager::*MemberPointerType)(ParameterList);
void catalogueTest( tstring testName, DebuggingManager* obj, MemberPointerType *nMemberFunction )
{
debugLog += _T("Status of ") + testName + _T(": ") + (obj->*nMemberFunction)() + _T("\r\n");
}
void catalogueStaticTest( tstring testName, bool DebuggingManager::nStaticFunction )
{
debugLog += _T("Status of ") + testName + _T(": ") + nStaticFunction + _T("\r\n");
}
最佳答案
类的静态成员函数最终与常规函数没有区别。它们实际上只是语法糖;该函数只是有一个包含 Classname::
的名称。
非静态成员完全是另一回事。关于非静态成员函数 (NSMF),有两点需要记住。
首先,每个非静态成员函数都可以访问它们所属类的非静态成员。即使您可以拥有同一类的两个对象碰巧存储不同的数据,这也是可能的。如果您有两个 std::string
对象,它们各自存储不同的字符串。对一个字符串执行 find
可以在一个字符串中返回找到的结果,但不会在另一个字符串中返回。
这是因为每个 NSMF 都有一个隐式的 this
指针。 this
不仅指类,而且指 NSMF 运行的实际对象。当您这样做时:
std::string aString("data");
aString.find("da");
find
函数接受一个字符串参数,但它也得到 aString
作为它的 this
。每次 find
查找其类的成员时,它都会查看 aString
的数据。
那么让我们看看您对 NSMF 的预期呼吁:
((*)nMemberFunction())
它从哪里获得 this
指针的对象?没有对象,NSMF 就无法访问对象的非静态成员,因为没有对象可供它在其中找到它们。这是不合法的。
因此,关于 NSMF 的第 1 条规则:您必须使用 NSMF 所属类(或其派生类)的实际实例来调用它们。您不能只使用 NSMF 指针并像调用函数指针一样调用它;您必须在该类型的事件对象上调用它。
规则 #2:NSMF 指针的语法真的很难看。
要定义一个名为 arg
的 NSMF 指针类型的变量(或参数),您可以这样做:
ReturnType (ClassName::*arg)(ParameterList);
其中ReturnType
是函数的返回类型,ParameterList
是函数接受的参数列表,ClassName
是名称NSMF 指针所属的类。
鉴于丑陋,通常最好将其包装在 typedef 中:
typedef ReturnType (ClassName::*MemberPointerType)(ParameterList);
因此创建了 typedef MemberPointerType
,它是一个 NSMF 指针。
给定一个名为 object
的对象,其类型为 ClassName
,您将调用成员指针 arg
,如下所示:
ReturnType value = (object.*arg)(Params);
Params
是您希望传递的参数。如果 object
是指向 ClassName
的指针而不是引用或值,那么您可以使用 object->*arg
。
还有一件事:您必须使用&
来获取成员指针名称。与函数指针不同,NSMF 指针不会自动转换为成员指针。你必须直接问他们。因此,如果 ClassName
有一个名为 Function 的成员,它符合上面的 ReturnType
和 ParameterList
,您将按如下方式填写 arg
:
arg = &ClassName::Function;
规则 #3:非静态成员指针不是指针。是的,它们可以设置为 NULL(从技术上讲,它们可以设置为 0),但它们不是指针。
大多数真正的 C 和 C++ 编译器将允许您将函数指针转换为 void*
并返回。标准考虑了这种未定义的行为,但这样做并非完全未知。在几乎所有 C++ 编译器上,您绝对不能使用 NSMF 指针执行此操作。实际上,sizeof(MemberPointerType)
的大小可能与 void*
的大小不同。
因此,NSMF 指针不是常规指针。不要这样对待他们。
关于c++ - 传递一个类成员函数作为函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7218519/
简而言之:我想从可变参数模板参数中提取各种选项,但不仅通过标签而且通过那些参数的索引,这些参数是未知的 标签。我喜欢 boost 中的方法(例如 heap 或 lockfree 策略),但想让它与 S
我可以对单元格中的 excel IF 语句提供一些帮助吗? 它在做什么? 对“BaselineAmount”进行了哪些评估? =IF(BaselineAmount, (Variance/Baselin
我正在使用以下方法: public async Task Save(Foo foo,out int param) { ....... MySqlParameter prmparamID
我正在使用 CodeGear RAD Studio IDE。 为了使用命令行参数测试我的应用程序,我多次使用了“运行 -> 参数”菜单中的“参数”字段。 但是每次我给它提供一个新值时,它都无法从“下拉
我已经为信用卡类编写了一些代码,粘贴在下面。我有一个接受上述变量的构造函数,并且正在研究一些方法将这些变量格式化为字符串,以便最终输出将类似于 号码:1234 5678 9012 3456 截止日期:
MySql IN 参数 - 在存储过程中使用时,VarChar IN 参数 val 是否需要单引号? 我已经像平常一样创建了经典 ASP 代码,但我没有更新该列。 我需要引用 VarChar 参数吗?
给出了下面的开始,但似乎不知道如何完成它。本质上,如果我调用 myTest([one, Two, Three], 2); 它应该返回元素 third。必须使用for循环来找到我的解决方案。 funct
将 1113355579999 作为参数传递时,该值在函数内部变为 959050335。 调用(main.c): printf("%d\n", FindCommonDigit(111335557999
这个问题在这里已经有了答案: Is Java "pass-by-reference" or "pass-by-value"? (92 个回答) 关闭9年前。 public class StackOve
我真的很困惑,当像 1 == scanf("%lg", &entry) 交换为 scanf("%lg", &entry) == 1 没有区别。我的实验书上说的是前者,而我觉得后者是可以理解的。 1 =
我正在尝试使用调用 SetupDiGetDeviceRegistryProperty 的函数使用德尔福 7。该调用来自示例函数 SetupEnumAvailableComPorts .它看起来像这样:
我需要在现有项目上实现一些事件的显示。我无法更改数据库结构。 在我的 Controller 中,我(从 ajax 请求)传递了一个时间戳,并且我需要显示之前的 8 个事件。因此,如果时间戳是(转换后)
rails 新手。按照多态关联的教程,我遇到了这个以在create 和destroy 中设置@client。 @client = Client.find(params[:client_id] || p
通过将 VM 参数设置为 -Xmx1024m,我能够通过 Eclipse 运行 Java 程序-Xms256M。现在我想通过 Windows 中的 .bat 文件运行相同的 Java 程序 (jar)
我有一个 Delphi DLL,它在被 Delphi 应用程序调用时工作并导出声明为的方法: Procedure ProduceOutput(request,inputs:widestring; va
浏览完文档和示例后,我还没有弄清楚 schema.yaml 文件中的参数到底用在哪里。 在此处使用 AWS 代码示例:https://github.com/aws-samples/aws-proton
程序参数: procedure get_user_profile ( i_attuid in ras_user.attuid%type, i_data_group in data_g
我有一个字符串作为参数传递给我的存储过程。 dim AgentString as String = " 'test1', 'test2', 'test3' " 我想在 IN 中使用该参数声明。 AND
这个问题已经有答案了: When should I use "this" in a class? (17 个回答) 已关闭 6 年前。 我运行了一些java代码,我看到了一些我不太明白的东西。为什么下
我输入 scroll(0,10,200,10);但是当它运行时,它会传递字符串“xxpos”或“yypos”,我确实在没有撇号的情况下尝试过,但它就是行不通。 scroll = function(xp
我是一名优秀的程序员,十分优秀!