【问题标题】:child class method pointer to method parent argument c++指向方法父参数c ++的子类方法指针
【发布时间】:2015-04-18 13:32:57
【问题描述】:

我想看到的可能很奇怪,我会尽可能地澄清。我在 ubuntu 14.04 和 C++11 上使用 gcc 4.8。

我想做的是:

  • 创建一个 A 类
  • 在 A 类中创建一个函数,作为参数
  • 指向同一类的类成员的指针
  • 创建一个继承自 A 的新类 B
  • 制作B类的新方法
  • 将指向 B 类的方法的指针指向父类 A 的方法作为参数

    class A{
        typedef void(A::*METHOD);        
    
        void executeMethod(METHOD arg){};
    }
    
    class B : A{
    
        void sampleMethod(){};
    
        void childMethod(){              
    
          this->executeMethod(&B::sampleMethod); //<== error
        }
    }
    

然而,这给我带来了代码块中的以下错误:

error: no matching function to call for 'B::executeMethod(void B::*)'

有没有办法解决这个问题? 我还需要做些什么来向您说明我要完成的工作吗?

【问题讨论】:

    标签: c++ class inheritance methods arguments


    【解决方案1】:

    问题是sampleMethod 不是A 的成员,它是B 的成员并且不能转换为void(A::*)

    您是否考虑过使用虚拟方法?

    【讨论】:

      【解决方案2】:
      typedef void(A::*METHOD);        
      

      METHOD 定义为void* 类型的指针,指向A 的成员变量,而不是指向A 的成员函数的指针。

      你需要:

      typedef void (A::*METHOD)();        
      

      即使进行了这种更改,您也不能使用 B 的成员函数作为参数传递到预期 METHOD 的位置。

      你可以把你想传递的函数设为A的虚成员函数并使用它。

      class A {
         protected:
            typedef void(A::*METHOD)();        
      
            void executeMethod(METHOD arg){};
      
         public:
            virtual void sampleMethod() = 0;
      };
      
      class B : public A {
      
         virtual void sampleMethod(){};
      
         void childMethod(){              
      
            this->executeMethod(&A::sampleMethod);
         }
      };
      

      【讨论】:

        【解决方案3】:

        要使可调用对象绑定到成员函数,您应该使用 std::bind。这将创建一个转发包装器,它将调用 sampleMethod 并预先指定一些参数。在这种情况下,“this”参数将被绑定。

        std::bind(&B::sampleMethod, this);

        【讨论】:

        • 首先OP不需要函数指针,他要求一个指向方法的指针。第二个std::bind() 不会生成函数指针。
        • 同意。我的术语很松散。我将进行编辑以更正措辞。
        【解决方案4】:

        不能直接从基类调用子方法,但可以使用模板:

        class A {
        public:
            template<class T>
            void executeMethod( void (T::*method)() )
            {
                (static_cast<T *>( this )->*method)();
            }
        };
        
        class B : public A {
        public:
            void sampleMethod() {}
            void childMethod() { executeMethod( &B::sampleMethod ); }
        };
        

        但更灵活的解决方案是使用std::functionstd::bind,因为这样您就可以传递签名不匹配的方法。

        class A {
        public:
            typedef std::function<void()> Method;
        
            void executeMethod( const Method &method )
            {
                method();
            }
        };
        
        class B : public A {
        public:
            void sampleMethod1() {}
            void sampleMethod2( int param ) {}
        
            void childMethod1() { executeMethod( std::bind( &B::sampleMethod1, this ); }
            void childMethod2() { executeMethod( std::bind( &B::sampleMethod2, this, 123 ); }
        };
        

        【讨论】:

        • typedef std::function 方法;给我错误:“函数”没有命名类型
        • @philsegeler 你需要包含&lt;functional&gt;
        猜你喜欢
        • 2017-04-13
        • 2010-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-21
        • 1970-01-01
        • 2010-12-05
        • 2021-12-10
        相关资源
        最近更新 更多