从指向对象的指针调用成员函数指针时调用错误的函数

Posted

技术标签:

【中文标题】从指向对象的指针调用成员函数指针时调用错误的函数【英文标题】:Bad function call in calling member function pointer from pointer to an object 【发布时间】:2020-04-23 20:20:39 【问题描述】:

所以我正在为 OOP 课程编写一个项目。我遇到了这种特殊性。 我有一个具有可自定义功能的类,例如:

#include<memory>  
#include<functional>
#include<iostream>
class foo 

private:
   std::function<void()> action = nullptr;
public:
    foo() = default;
    void add_action(std::function<void()> lambda_expression)
    
        action = lambda_expression;
    
    void do_action() 
    
        action();
    
;

如果我主要做以下事情

std::shared_ptr<foo> sp;

    foo obj= foo();
    sp = std::make_shared<foo>(obj);
    obj.add_action([]() std::cout << "hello world" << std::endl; );

sp->do_action();

它将不变地导致以下错误:“在 lambda expression.exe 中的 0x75284192 处出现未处理的异常:Microsoft C++ 异常:std::bad_function_call 在内存位置 0x0058F710。”

进入调试汽车,我可以看到它将操作读取为“空”。

但是,这样切换顺序

obj.add_action([]() std::cout << "hello world" << std::endl; );
sp = std::make_shared<foo>(obj);

或者使用共享指针调用add_action():

sp = std::make_shared<foo>(obj);
sp->add_action([]() std::cout << "hello world" << std::endl; );

两者都工作正常! (打印“你好世界”)

注意:与此代码对应的普通指针在这两种情况下都不起作用。

有人知道是什么原因造成的吗?我要调查它,但似乎相当微妙! 如果我找到了将其发布在此线程上的原因。 谢谢!

在 Visual Studio 2019 版本 16.4.3 中工作

【问题讨论】:

【参考方案1】:
foo obj= foo();

obj是默认构造函数构造的,所以std::function中没有目标。

sp = std::make_shared<foo>(obj);

您在堆上创建Foo 的新实例,其生命周期由智能指针sp 管理。这个新创建的Foo 对象在std::function 中也没有目标,因为在执行复制操作时obj 没有目标。 Foo(const Foo&amp;) 刚刚复制了一个空函数。

sp 构造完成后,这两个Foo 实例完全不相关。通过访问sp,您不会修改obj,反之亦然。所以obj.add_action 无法更新Foostd::functionshared_ptr 构造。

【讨论】:

以上是关于从指向对象的指针调用成员函数指针时调用错误的函数的主要内容,如果未能解决你的问题,请参考以下文章

存储指向成员函数的指针不适用于 clang++

C++ Primer 5th笔记(chap 19 特殊工具与技术)将成员函数用作可调用对象

类的成员函数this指针

c++怎样将指向【成员函数】的指针强转成指向【普通函数】的指针

C++ 类成员函数地址

通过指针C++调用成员函数,对象为空?