Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以从基类使用的另一个类中的派生类保存指向函数成员的指针_C++_Reference_Member Function Pointers - Fatal编程技术网

C++ 是否可以从基类使用的另一个类中的派生类保存指向函数成员的指针

C++ 是否可以从基类使用的另一个类中的派生类保存指向函数成员的指针,c++,reference,member-function-pointers,C++,Reference,Member Function Pointers,基本上我有一个类,比如说参数,它有一个get和set变量 我还有一个基类,比如说Vehicle,它有一个方法registerParameter(…),该方法将指向函数成员的指针作为getter,将指向函数成员的指针作为setter。然后,该方法将这两个指针写入parameter类的对象中,并将该对象抛出到向量中 最后但并非最不重要的一点是,我们有一个派生类,比如说Car,我们调用registerParameter(…),其中字符串“color”作为参数名,以及这个派生类的getter和sette

基本上我有一个类,比如说
参数
,它有一个get和set变量

我还有一个基类,比如说
Vehicle
,它有一个方法
registerParameter(…)
,该方法将指向函数成员的指针作为getter,将指向函数成员的指针作为setter。然后,该方法将这两个指针写入parameter类的对象中,并将该对象抛出到向量中

最后但并非最不重要的一点是,我们有一个派生类,比如说
Car
,我们调用
registerParameter(…)
,其中字符串
“color”
作为参数名,以及这个派生类的getter和setter

代码中的示例:

参数文件

#ifndef BASE_H
#define BASE_H
#include "base.h"

class Parameter
{
    std::string (Base::*get)();
void (Base::*set)(std::string);
};

#endif
基本文件

#ifndef PARAMETER_H
#define PARAMETER_H
#include <vector>
#include "parameter.h"

class Base
{
  public:
std::vector<Parameter> list;
void registerNew(std::string (Base::*get)(), void (Base::*set)(std::string))
    {
        Parameters parameter;
        parameter.get = get;
        parameter.set = set;
        list.push_back(parameter);
}
};

#endif

我已经想了好几天了,我真的需要解决方案,直到周五晚上。

你不能做你想做的事:

类型
std::string(基::*)()
std::string(派生::*)()
非常不同<代码>标准::字符串(派生::*)()无法自动转换为标准::字符串(基::*)()

以下面的场景为例

struct Base
{
    int foo() { return 10; }
};

struct Derived : Base
{
    int bar() { return 20; }
};

int main()
{
    Base base;

    int (Base::*bf)() = &Base::foo;
    (base.*bf)(); // Should be able to call Base:foo(). No problem.

    bf = &Derived::bar; // This is a compiler error. However, if this were allowed....
    (base.*bf)(); // Call Derived::bar()?? That will be a problem. base is not an
                  // instance of Derived.
}
更新

您可以执行以下操作:

#include <string>
#include <vector>

class Base;

// Create a base class Functor that provides the interface to be used by
// Base.
struct Functor
{
   virtual ~Functor() {}
   virtual std::string get(Base& base) = 0;
   virtual void set(Base& base, std::string) = 0;
};

// Create a class template that implements the Functor interface.
template <typename Derived> struct FunctorTemplate : public Functor
{
   // typedefs for get and set functions to be used by this class.
   typedef std::string (Derived::*GetFunction)();
   typedef void (Derived::*SetFunction)(std::string);

   // The constructor that uses the get and set functions of the derived
   // class to do itw work.
   FunctorTemplate(GetFunction get, SetFunction set) : get_(get), set_(set) {}

   virtual ~FunctorTemplate() {}

   // Implement the get() function.
   virtual std::string get(Base& base)
   {
      return (reinterpret_cast<Derived&>(base).*get_)();
   }

   // Implement the set() function.
   virtual void set(Base& base, std::string s)
   {
      (reinterpret_cast<Derived&>(base).*set_)(s);
   }

   GetFunction get_;
   SetFunction set_;
};

class Base
{
   public:
      std::vector<Functor*> functorList;

      void registerFunctor(Functor* functor)
      {
         functorList.push_back(functor);
      }
};

class Derived : public Base
{
  public:
    Derived() 
    {
       // Register a FunctorTemplate.
       registerFunctor(new FunctorTemplate<Derived>(&Derived::getColor, 
                                                    &Derived::setColor));
    }

    std::string getColor()
    {
        return this->color;
    }

    void setColor(std::string newColor)
    {
        this->color = newColor;
    }
  private:
    std::string color;
};
#包括
#包括
阶级基础;
//创建一个基类函子,该函子提供要由
//基地。
结构函子
{
虚~函子(){}
虚拟标准::字符串获取(基和基)=0;
虚空集(基和基,标准::字符串)=0;
};
//创建实现Functor接口的类模板。
模板结构FunctorTemplate:公共函子
{
//typedefs用于该类要使用的get和set函数。
typedef std::string(派生::*GetFunction)();
typedef void(派生::*SetFunction)(std::string);
//使用派生函数的get和set函数的构造函数
//上课做作业。
FunctorTemplate(GetFunction get,SetFunction set):get_(get),set_(set){
虚拟~FunctorTemplate(){}
//实现get()函数。
虚拟标准::字符串获取(基本和基本)
{
返回(重新解释施法(基础)。*get_uu)();
}
//实现set()函数。
虚拟空集(基和基,标准::字符串s)
{
(重新解释铸造(基础)。*设置(s);
}
GetFunction获取;
设置函数集;
};
阶级基础
{
公众:
向量函子表;
无效注册表函数(函子*函子)
{
functorList.push_back(函子);
}
};
派生类:公共基
{
公众:
派生的()
{
//注册FunctorTemplate。
registerFunctor(新FunctorTemplate(&D)派生::getColor,
&派生::setColor));
}
std::string getColor()
{
返回此->颜色;
}
void setColor(std::string newColor)
{
此->颜色=新颜色;
}
私人:
字符串颜色;
};

您的基类应该知道派生类。这听起来很复杂,但问题已经解决了:

template<typename DERIVED> class Base
{
public:
   class Parameter {
     std::string (DERIVED::*get)();
     void (DERIVED::*set)();
   };
private:
   std::list<Parameter> list;
   // ...
};

class Derived : public Base<Derived> // !!!
{
   registerNew(&Derived::getColor, &Derived::setColor);
};
模板类基类
{
公众:
类参数{
std::string(派生::*get)();
void(派生::*set)();
};
私人:
std::列表;
// ...
};
派生类:公共基/!!!
{
registerNew(&Derived::getColor,&Derived::setColor);
};

这个解决方案被称为奇怪的循环模板模式(CRTP)。

所以您的问题是getColor和setColor在registerNew中是不可接受的?你可以放松一点规则,而不是得到一个严格的函数指针,只要让函数receive
void*
,但是当你想使用它时,你就必须正确地抛出它,尽管问题标题上缺少问号,它说的是我需要的。@inneedofhelp:这是个非常糟糕的主意。最好是使用
std::function
std::bind
派生的*。还有其他选择吗?还是解决这个问题的方法?@PascalNeubert:这不是必要的,只是方便(省去了重复模板参数)。
template<typename DERIVED> class Base
{
public:
   class Parameter {
     std::string (DERIVED::*get)();
     void (DERIVED::*set)();
   };
private:
   std::list<Parameter> list;
   // ...
};

class Derived : public Base<Derived> // !!!
{
   registerNew(&Derived::getColor, &Derived::setColor);
};