如果我有:
class A {
void foo();
};
class B {
void foo();
};
有没有办法收集A
和B
类型的实例来循环它们以调用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不是必需的。)
答案 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;
}