如何循环异构 类 的实例以调用具有相同名称和参数的方法?

How can I cycle on instances of heterogenous classes to call methods with identical name and parameters?

如果我有:

class A {
    void foo();
};

class B {
    void foo();
};

有没有办法收集AB类型的实例,循环调用foo()方法?例如使用一些宏或指针和一些特殊的数据类型?或者收集函数指针?

以下伪代码可能让您明白我的意思。

int main () {
    A a;
    B b;

    hypothetical_container_t hypothetical_container; 
    hypothetical_container.push_back(a);
    hypothetical_container.push_back(b);

    [...]//Do stuff with a, do other stuff with b

    for (hypothetical_container_t::iterator ii = hypothetical_container.begin(); ii != hypothetical_container.end(); ++ii) {
        ii->foo();
    }
}

用例有一堆 boost::shared_ptr 个不同类型 T 的变量,并对所有变量调用 .reset()。 (我知道在这个例子中调用 reset 是不必要的)。

您应该可以使用虚拟 class:

virtual class C {
    public:
        virtual void foo() = 0;
}

class A : public C {
    virtual void foo();
};

class B : public C {
    virtual void foo();
};

然后在主要你可以有:

A a;
B b;

std::vector<C*> vec;
vec.push_back(&a);
vec.push_back(&b);

然后可以迭代调用foo方法,vector的所有成员都保证实现

WRT boost::shared_ptr,我不太熟悉,但我想你可以这样做:

boost::shared_ptr<C> a(new A);
boost::shared_ptr<C> b(new B);

std::vector<boost::shared_ptr<C>> vec;

How can I cycle on instances of heterogenous classes to call methods with identical name and parameters?

这需要模板!

#include <memory>
#include <iostream>

void    chain_call_reset()
{
}

template<typename Arg, typename ... Rest>
void    chain_call_reset(Arg&& arg, Rest&&... rest)
{
  arg.reset();
  chain_call_reset(rest...);
}

int     main()
{
  std::shared_ptr<int>  ptr = std::make_shared<int>(42);
  std::shared_ptr<char>  ptr2 = std::make_shared<char>('c');
  std::shared_ptr<float>  ptr3 = std::make_shared<float>(4.2);

  chain_call_reset(ptr, ptr2, ptr3);

  std::cout << std::boolalpha << !!ptr << std::endl;
  std::cout << std::boolalpha << !!ptr2 << std::endl;
  std::cout << std::boolalpha << !!ptr3 << std::endl;
}

如果您的类型之间没有共同的层次结构,模板是可行的方法:)

如果您可以选择更改 类 A 和 B,我建议您使用

如果你没有那个选项,我有以下建议。

#include <memory>
#include <iostream>
#include <vector>

struct A {
    void foo(){}
};

struct B {
    void foo(){}
};

struct Wrapper
{
   virtual void foo() = 0;
};

template <typename T> struct WrapperImpl : Wrapper
{
   WrapperImpl(T& obj) : obj_(obj) {}
   void foo() {obj_.foo();}
   T& obj_;
};

template <typename T>
std::unique_ptr<Wrapper> makeWrapper(T& t)
{
   return std::unique_ptr<Wrapper>(new WrapperImpl<T>(t));
}

int main()
{
   std::vector<std::unique_ptr<Wrapper>> v;
   A a;
   B b;
   v.push_back(makeWrapper(a));
   v.push_back(makeWrapper(b));

   for ( auto& item : v )
   {
      item->foo();
   }
}

您的任务需要类型省略。 Boost::any 就是一个很好的例子。 调用普通函数的简单方法:

#include <iostream>
#include <memory>
#include <vector>

class Any
{
    // Content
    // =======

    private:
    class ContentInterface
    {
        public:
        virtual ~ContentInterface() {}
        virtual void call() const {}
    };

    template <typename T>
    class Content : public ContentInterface
    {
        private:
        T& m_object;

        public:
        Content(T& object)
        :   m_object(object)
        {}

        virtual void call() const { m_object.foo(); }
    };

    // use boost here:    
    typedef std::shared_ptr<ContentInterface> content_ptr;

    // Constructionn
    // =============

    public:
    Any()
    {}

    template<typename T>
    Any(T& object)
    :   m_content(new Content<T>(object))
    {}

    void call() const { m_content->call(); }

    private:
    content_ptr m_content;
};

struct A {
    void foo() { std::cout << "A\n"; }
};

struct B {
    void foo() { std::cout << "B\n"; }
};

int main(void)
{
    typedef std::vector<Any> container;
    A a;
    B b;
    container v;
    v.push_back(a);
    v.push_back(b);
    for(container::const_iterator pos = v.begin(); pos != v.end(); ++pos)
        pos->call();
}

另一种选择是 std::function 和 std::bind(同样,在 C++98 中使用增强功能):

#include <functional>
#include <iostream>
#include <vector>

int main()
{
    typedef std::function<void ()> function;
    typedef std::vector<function> container;
    A a;
    B b;
    container v;

    v.push_back(std::bind(&A::foo, a));
    v.push_back(std::bind(&B::foo, b));
    for(container::const_iterator pos = v.begin(); pos != v.end(); ++pos)
        (*pos)();
}

如果您无法访问可变参数模板,您可以使用 boost::fusion

#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/for_each.hpp>

struct  reset
{
  template<typename T>
  void operator()(T& t) const
  {
    t.reset();
  }
};

int     main()
{
  boost::shared_ptr<int>  ptr = boost::make_shared<int>(42);
  boost::shared_ptr<char>  ptr2 = boost::make_shared<char>('c');
  boost::shared_ptr<float>  ptr3 = boost::make_shared<float>(4.2);


  boost::fusion::vector<boost::shared_ptr<int>&, boost::shared_ptr<char>&, boost::shared_ptr<float>& > vec
    = boost::fusion::make_vector(boost::ref(ptr), boost::ref(ptr2), boost::ref(ptr3));

  boost::fusion::for_each(vec, reset());

  std::cout << std::boolalpha << !!ptr << std::endl;
  std::cout << std::boolalpha << !!ptr2 << std::endl;
  std::cout << std::boolalpha << !!ptr3 << std::endl;
}