繁体   English   中英

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

[英]Is it possible to save pointer to function member from a derived in another class used by a base class

基本上,我有一个类,它具有一个get和set变量的Parameter

我还有一个基类,比如说Vehicle ,它的方法registerParameter(...)将指向函数成员的指针作为getter和指向函数成员的指针作为setter。 然后应该假定此方法将这两个指针写入参数类的对象中,然后将此对象放入向量中。

最后但并非最不重要的一点是,我们有一个派生类,比如说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

派生文件

class Derived
{
  public:
    Derived derived() 
    {
        registerNew(&getColor, &setColor);
    }

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

    std::string setColor(std::string newColor)
    {
        this->color = newColor;
    }
  private:
    std::string color;
};

我已经考虑了好几天了,直到星期五晚上我才真正需要解决方案。

您无法执行正在尝试的操作:

std::string (Base::*)()std::string (Derived::*)()类型非常不同。 std::string (Derived::*)()无法自动转换为std::string (Base::*)()

请采取以下情况。

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;
};

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

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);
};

此解决方案称为“好奇重复模板模式(CRTP)”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM