简体   繁体   English

C ++ ::成员函数数组

[英]C++:: Array of Member Functions

I want to store an array of Member Functions of different Classes. 我想存储不同类的成员函数数组。 Just a repetition here: 这里只是重复:

Requirements: 要求:

  • TypeOf Class TypeOf
  • Instance of Class containing the Function 包含函数的类的实例
  • AddressOf the Member Function AddressOf成员函数
  • Member Function parameters 成员函数参数

What I can store: 我可以存储什么:

  • Instance of Class containing the Function 包含函数的类的实例
  • AddressOf the Member Function. 成员函数的AddressOf
  • Member Function parameters 成员函数参数

Normally, you don't need to store the Class type whatsoever, since you can make an array pointer to the Class type. 通常,您无需存储任何Class类型,因为您可以使数组指针指向Class类型。 The reason I can't do that is because the Class types I take in are unknown and different. 我之所以不能这样做,是因为我接受的Class类型是未知且不同的。 The Class is going to be used in many different projects where Class types are unknown. 该类将用于许多类类型未知的项目中。

I need to store different types of Classes into the Array/List, in which case I just stored the addresses of the classes into an array pointer. 我需要将不同类型的类存储到数组/列表中,在这种情况下,我只是将类的地址存储到数组指针中。

My Problem: When I'm about to call the Member Function, I need to cast the Class address to the Class type, but I don't know what the type is to cast to. 我的问题:当我要调用成员函数时,我需要将Class地址转换为Class类型,但是我不知道该转换为哪种类型。

Example Code (Not tested - written real quickly): 示例代码(未经测试-快速编写):

class A
{
    public:
        void test1(int i);
};

class B
{
    public:
        void test2(char c);
};

class Container
{
    long* objects;
    long* funcs;
    int index;

    public:

        Container()
        {
            objects = new long[5];
            funcs = new long[5];
            index = 0;
        }

        template <class C, typename Types ...>
        void Add(C *obj, void (C::*func)(Types ...))
        {
            objects[index++] = (long)obj;
            funcs[index++] = (long)func;
        }

        typename <Types ...>
        void Call(int inx, Types ... values)
        {
            void (*func)(Types ...) = (void (*)(Types ...))funcs[inx];

            // This is where I've got trouble. I don't store the Class 
            // types, so I don't know what pointer Class type to cast 
            // the Class Instance address to.
            (((*???)objects[inx])->*func)(values ...);
        }
};

Thanks in advance. 提前致谢。 Ask ahead if there are any holes or any questions. 事先询问是否有孔或任何问题。

Can you constrain this a little bit on the signature of the member functions? 您可以在成员函数的签名上对此加以限制吗? If so, instead of storing pointers to objects and member functions separately, you can store bound functions. 如果是这样,您可以存储绑定的函数,而不必分别存储指向对象和成员函数的指针。

template<typename... Args>
class Container {
public:
    typedef std::function<void (Args...)> F;

    template <class C>
    void Add(C* obj, void (C::*func)(Args ...))
    {
        functions.push_back( [=](Args... args) {(obj->*func)(args...);} );
    }

    void call(size_t i, Args... args)
    {
        functions[i](args...);
    }

private:
    std::vector<F> functions;
};

IMHO, your posting reads like it might be an interesting polymorphic programming challenge, but with the added requirement, "no polymorphism" ... in which case you are to learn the more difficult approach. 恕我直言,您的帖子看起来像是一个有趣的多态编程挑战,但是有一个额外的要求,即“禁止多态” ...在这种情况下,您将学习更困难的方法。

What I have to address your stated problem: 我要解决您所说的问题:

When I'm about to call the Member Function, I need to cast the Class address to the Class type, but I don't know what the type is to cast to. 当我要调用成员函数时,我需要将Class地址转换为Class类型,但是我不知道该类型转换为什么类型。

used to be called a Thunk (back when I first encountered it). 曾经被称为Thunk(当我第一次遇到它的时候)。 In a (relatively) recent search, I have not found this idea under that name (and did find several other things called a thunk). 在(相对)最近的搜索中,我没有用这个名字找到这个想法(并且确实找到了其他一些叫做thunk的东西)。 The explanation for the name I once read was something like because "it encapsulates things that I already thunk". 我曾经读过的名字的解释就像是因为“它封装了我已经笨拙的东西”。

Note that with a thunk, NO casting is required (because you already thunked it) 请注意,使用重击时,不需要强制转换(因为您已经将其重击了)

Use the thunk as the object in your Container. 将thunk用作容器中的对象。

Oh, and since you marked this C++, you really should use std::vector < PVThunk_t >. 哦,既然您已标记此C ++,则实际上应该使用std :: vector <PVThunk_t>。

  // ////////////////////////////////////////////////////////////////////
  // Pure Virtual Thunk_t: an abstract base class
  class PVThunk_t
  {
  public:
     virtual ~PVThunk_t(){}

     virtual void operator()(void* v) = 0;
     virtual void exec      (void* v) = 0;
  };
  // pure-virtual requires derived objects to implement both methods

// ///////////////////////////////////////////////////////////////////////
// template class - make it easy to create thunk for any class T
template <class T>
class Thunk_t : PVThunk_t
{
public:
   // constructor - takes pointer to an object and pointer to a member and stores
   // them in two private variables
   Thunk_t( T*    anInstance,        // pointer to an instance of class T
            void* (T::*aMethod)()) : // pointer to a  method   of class T, no parameter, returns void
      m_instance (anInstance),
      m_method   (aMethod)
      {
         assert  (m_instance);
         asssert (m_method);
      }

   Thunk_t( T*  anInstance,        // pointer to an instance of class T
            T*  (T::*aMethod)()) :  // pointer to a  method   of class T, no parameter, returns T*
      m_instance (anInstance),
      m_method   (aMethod)
      {
         assert  (m_instance);
         asssert (m_method);
      }

   virtual ~Thunk_t() { }

   // override operator "()"
   virtual void* operator()(void* v) { return((*m_instance.*m_method)(v)); }

   // override function "exec"
   virtual void* exec(void* v) { return((*m_instance.*m_method)(v)); }

private:
   T*        m_instance;         // pointer to object of T
   void (T::*m_method)(void*);   // pointer to method attribute of T with void* param

}; // template <class T>  class Thunk_t : public PVThunk_t

Note the proper mechanism to declare m_instance and m_method pointers. 注意声明m_instance和m_method指针的正确机制。


If you need to use methods with a variable number of parameters, I suggest passing a struct pointer (with appropriate adjustments or additions to the Thunk. The single method parameter would always be a pointer to the struct, and its type or content can then be inferred by the method invoked. 如果您需要使用带有可变数量参数的方法,建议您传递一个struct指针(对Thunk进行适当的调整或添加。单个方法的参数始终是指向该struct的指针,然后可以将其类型或内容设置为由调用的方法推断。

I have not used this Thunk for a long time, because, well, polymorphism is superior in every way. 我已经很长时间没有使用过Thunk了,因为好吧,多态性在各个方面都优越。 But Thunk still compiles, so it will probably work. 但是Thunk仍然可以编译,因此它可能会起作用。

update - noticed that the virtual methods didn't match. 更新-注意虚拟方法不匹配。 fixed 固定

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

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