【问题标题】:member function referring to an object's member function引用对象的成员函数的成员函数
【发布时间】:2020-05-29 01:47:46
【问题描述】:

我是一个 c++ 菜鸟,所以如果这个问题的结构不正确,请提前道歉。

我有一个实例化不同类的对象的类,我希望主类的成员函数(请原谅我的幼稚语言)依次引用在主类中实例化的对象的成员函数类。

我附上了一个 sn-p 供参考

foo.h

class foo {
public : 

int data;
void printFunc(){
cout<< "data is"<< data;
}

};

bar.h

class bar {

public:
void updatebarr ();
}

bar.cpp

bar::bar()
{
foo foo1;
foo1.data = 1; 
// the line below is flagged as syntax error
// I want the object of type bar's updatebarr() function to be essentially be calling 
// foo::PrintFunc(). I figured this "should" work as the signatures are identical.
this->updatebarr = &foo1.printFunc(); 
}

我得到的错误是“必须调用对非静态成员函数的引用”,

【问题讨论】:

  • 如果你希望“bar 类型的对象的updatebarr() 函数本质上是调用foo::PrintFunc”然后在updatebarr() 中调用PrintFunc,就是这样。你不能通过设置updatebarr 来实现这一点,就像它是某种指针一样。 C++ 不能以这种方式工作。学习 C++ 没有捷径,除非通过精心编写的 C++ 教科书提供的有指导的、有组织的方法。随机猜测做某事的正确 C++ 语法的机会绝对为零,如果不是负数的话。 C++ 是当今使用的最复杂的通用编程语言。
  • 好吧,如果您是 C++ 新手,我不建议您这样做。成员函数指针在 C++ 中很少使用。通常,可以从使用带有虚函数调用的 OOP 方法开始。如果需要通用回调,则应考虑将std::function 与某种高级 C++ 的 lambda 一起使用。话虽如此,鉴于foo1 是构造函数中的局部变量,如果在构造对象后调用updatebarr,回调将具有未定义的行为并且可能会崩溃……因此拥有该类型的成员几乎没有意义.

标签: c++ constructor member-functions


【解决方案1】:

签名可能看起来很相似,但它们不是免费函数,而是member functions。看看这个常见问题解答!

第一个的类型是:void (foo::*)(),第二个是void (bar::*)()。看出区别了吗?

它们只能在各自类型的对象上调用。你可以这样做:

class bar {
  public:
    void updatebarr(foo& f) {
      f.printFunc();
    }
};

【讨论】:

    【解决方案2】:

    指向成员方法的指针无法按照您尝试的方式工作。您所拥有的不仅是语法错误,而且还是逻辑错误,因为foo1 将超出范围并在bar() 退出时被销毁,从而使updatebarr 在无效的printFunc() 上调用@987654328 @对象。

    对于您正在尝试的内容,您需要更多类似的东西:

    foo.h

    class foo {
    public : 
        int data;
        void printFunc(){
            cout << "data is " << data;
        }
    };
    

    bar.h

    #include "foo.h"
    
    class bar {
    private:
        foo foo1;
    public:
        bar();
        void updatebarr();
    };
    

    bar.cpp

    #include "bar.h"
    
    bar::bar()
    {
        foo1.data = 1; 
    }
    
    void bar::updatebarr()
    {
        foo1.printFunc();
    }
    

    main.cpp

    #include "bar.h"
    
    int main()
    {
        bar b;
        b.updatebarr();
        return 0;
    }
    

    Live Demo

    或者,您可以将 updatebarr() 设为通过 lambda 调用 printFunc()std::function,例如:

    foo.h

    class foo {
    public : 
        int data;
        void printFunc(){
          cout << "data is " << data;
        }
    };
    

    bar.h

    #include <functional>
    #include "foo.h"
    
    class bar {
    private:
        foo foo1;
    public:
        bar();
        std::function<void()> updatebarr;
    };
    

    bar.cpp

    #include "bar.h"
    
    bar::bar()
    {
        foo1.data = 1; 
        updatebarr = [&](){ foo1.printFunc(); };
    }
    

    main.cpp

    #include "bar.h"
    
    int main()
    {
        bar b;
        b.updatebarr();
        return 0;
    }
    

    Live Demo

    在这种情况下,您可以让 lambda 捕获 foo 对象的副本,这将为您提供非常接近原始尝试的结果,例如:

    foo.h

    class foo {
    public : 
        int data;
        void printFunc() const {
          cout << "data is " << data;
        }
    };
    

    bar.h

    #include <functional>
    
    class bar {
    public:
        bar();
        std::function<void()> updatebarr;
    };
    

    bar.cpp

    #include "bar.h"
    #include "foo.h"
    
    bar::bar()
    {
        foo foo1;
        foo1.data = 1; 
        updatebarr = [foo1](){ foo1.printFunc(); };
    }
    

    main.cpp

    #include "bar.h"
    
    int main()
    {
        bar b;
        b.updatebarr();
        return 0;
    }
    

    Live Demo

    【讨论】:

      猜你喜欢
      • 2018-11-24
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      相关资源
      最近更新 更多