代码之家  ›  专栏  ›  技术社区  ›  MWRazer

在类-C上具有作为属性的函数++

  •  -1
  • MWRazer  · 技术社区  · 2 年前

    我希望在C++中创建一个类,它可以具有可变函数作为其单独属性之一。有什么标准的方法可以实现这一点吗?语法会是什么样子?

    例如,我尝试过并想做的事情:

    #include <iostream>
    
    class Thing {
      private:
        
        int val;
        
        void func();
        
      public:
        
        Thing(int val = 0) {
          this->val = val;
        }
        
        void setFunc(void func()) { this->func() = func; }
    
        void useFunc() { this->func(); }
        
    };
    
    int main() {
      
      Thing thing1 = Thing(1);
      
      thing1.setFunc({
        
        std::cout << "i am thing 1, my value is: " << this->val;
        
      });
      
      thing1.useFunc();
      
      return 0;
    
    }
    
    

    我不确定像这样的东西的语法会是什么样子,或者是否需要指针。这(可能很明显)返回了几个错误,它们是:

    ./main.cpp:16:46: error: expression is not assignable
        void setFunc(void func()) { this->func() = func; }
                                    ~~~~~~~~~~~~ ^
    ./main.cpp:28:51: error: invalid use of 'this' outside of a non-static member function
        std::cout << "i am thing 1, my value is: " << this->val;
                                                      ^
    

    我意识到我可以使用很多不是函数的属性,然后有一种方法使用这些属性来确定结果,但我不想这样做,因为这需要更多的属性,我想尝试一些不同的东西来学习如何做。在这个例子中,做我想做的事情没有意义,但这只是一个例子。

    0 回复  |  直到 2 年前
        1
  •  1
  •   user4581301    2 年前

    步骤1:定义一个函数指针!

    class Thing {
      private:
    
        int val;
        // void func(); declares a function that will be defined later
        // not what we want.
        using func_ptr = void (*)(); // define a new type. It make everything 
                                     // that follows much easier 
        func_ptr func; // declares func to be a pointer to a function
    
      public:
    
        Thing(int val = 0): val(val) // use member initializer list
                                     // all members must be initialized
                                     // before entering the body of the
                                     // constructor. not that important
                                     // for an int, but very important for
                                     // types with expensive initialization
                                     // or no default initialization
        {
        }
    
        void setFunc(func_ptr func)  // pass a function pointer
        {
            this->func = func; // Do not call the function!
                               // avoid reusing names in the same scope.
                               // It only leads to trouble
        }
    
        void useFunc()
        {
            func(); // which func is not ambiguous here. No need for this
        }
    };
    

    步骤2:分配函数!

      thing1.setFunc({
        
        std::cout << "i am thing 1, my value is: " << this->val;
        
      });
    

    看起来你正试图使用 Lambda Expression 。这里有几个问题。

    1. 语法错误。C++不是一种值得猜测的语言。 Get a good book or two 并以可控的方式学习语法。另一种选择是缓慢、痛苦和不值得做。

    正确的语法看起来像

      thing1.setFunc([](){
    
          std::cout << "i am thing 1, my value is: " << this->val;
    
        });
    
    1. 不幸的是,Lambda不知道它与 thing1 它也不是 Thing 所以它不能使用 this 。这有点让人欲罢不能。Lambda需要 俘虏 事物1 ,但是一旦捕获,就不能再使用函数指针了。它们太简单了,无法处理捕获。进来 std::function

    3.从 std::函数

    #include <iostream>
    #include <functional>
    
    class Thing {
      private:
    
        int val;
        using func_ptr = std::function<void ()>; 
        func_ptr func; 
    
      public:
    
        Thing(int val = 0): val(val) 
        {
        }
    
        void setFunc(func_ptr func)  
        {
            this->func = func; 
        }
    
        void useFunc()
        {
            func(); 
        }
    
        int get_val()
        {
            return val;
        }
    };
    int main() {
    
      Thing thing1 = Thing(1);
      thing1.setFunc([thing1](){ // captures by value. Not always what you 
                                 // want, but generally the safest option.
                                 // Just fine for a simple example like this
          std::cout << "i am thing 1, my value is: " << thing1.val;
    
        });
    
      thing1.useFunc();
    
      return 0;
    
    }
    

    但这仍然不起作用,因为 Thing::val 是私人成员,无法从外部访问 事情 或的朋友 事情 Lambda两者都不是,也不容易被塑造成一体。A)Lambda必须调用 事情 成员函数来做真正的工作,毫无意义,因为你会放弃所有这些繁琐的工作,直接调用成员函数,B)你为 物品::val Lambda使用你制造的吸气剂 物品::val public

    B看起来是最好的选择。但如果你需要的逻辑必须改变呢 事物1 ?这需要一个。。。

    第四步:找到一个更简单的答案来解决首要问题。