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

时间:2015-04-15 15:06:55

标签: c++ methods c++98

如果我有:

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

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

5 个答案:

答案 0 :(得分:3)

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

如果您没有该选项,我有以下建议。

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

答案 1 :(得分:2)

您应该能够使用虚拟课程:

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方法,该方法的所有成员都可以保证实现。

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;

答案 2 :(得分:1)

  

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

这需要模板!

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

如果您的类型之间没有共同的层次结构,那么模板就是:)

答案 3 :(得分:1)

您的任务需要输入类型。 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 with std :: bind(再次使用boost功能,在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)();
}

答案 4 :(得分:0)

如果您无权访问可变参数模板,可以使用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;
}