【问题标题】:collect different types of class and call their methods in c++收集不同类型的类并在 C++ 中调用它们的方法
【发布时间】:2015-11-28 14:29:04
【问题描述】:

C++中有没有办法收集不同类型的类并调用它们的方法? 我想做的是如下,

template<namespace T>
class A
{
    A method_A1(T a)
    {
        ...
    }

    void method_A2(int aa)
    {
        ...
    }

        ...
};

class B
{
    ...
};

class C
{
    ...
};

class D
{
    ...
};

A<B> *b;
A<C> *c;
A<D> *d;

b -> method_A2(3);
c -> method_A2(5);

在这个代码对象 b,c,d 中,它们是完全不同的对象,对吧?不相关的。 但是我想用数组绑定它们,所以...

z[0] = b;
z[1] = c;
z[2] = d;

像这样。 我找到了一些解决方案,但是这些解决方案仅用于收集不同的类型。 (对继承对象使用 void* 数组或向量)我也想访问它们的方法。

z[0] -> method_A2(3);
z[1] -> method_A3(5);

像这样。 在这种情况下我该怎么办?

提前致谢。

【问题讨论】:

  • 编译器如何知道 z[0] 具有 method_A2 除非 z 是一个对象数组,它们都具有 method_A2?如果类之间没有公共接口,在 C++ 中就无法做到这一点。
  • 如果函数 method_A1 没有使用模板类型,您可以添加一个带有纯虚函数的基类,A 将从中继承。
  • 最接近标准 C++ 的是std::tuple。但一切都需要在编译时收集

标签: c++ templates


【解决方案1】:
typedef boost::variant<A<B>, A<C>, A<D>> AVariant;
std::array<AVariant, 3> z;

z[0] = *b;
z[1] = *c;
z[2] = *d;

然后您可以根据需要检查每个元素的类型,或者使用boost::static_visitor“访问”它们,如下所示:http://www.boost.org/doc/libs/release/doc/html/variant.html

【讨论】:

    【解决方案2】:

    为什么不使用继承多态。我已经发布了一个示例,说明究竟可以解决您的问题。见main函数:

    #include <iostream>
    
    class weapon {
    
     public:
      int fireRate;
      int bulletDamage;
      int range;
      int activeBullet;
    
     public:
      virtual void fire(void) {std::cout << "machine " << '\n';}
      virtual ~weapon() {std::cout << "destructor is virtual" << '\n';}
    };
    
    class machineGun: public weapon {
     public: 
      void fire(void) {std::cout << "machine gun firing" << '\n';}
      ~machineGun(void) { std::cout << "machine gun destroyed" << '\n';}
    };
    
    class flamer: public weapon {
     public: 
      void fire(void) {std::cout << "flamer firing" << '\n';}
      ~flamer(void) {std::cout << "flamer destroyed" << '\n';}
    };
    
    int main(void)
    {
        const int count = 2;
        weapon *weapons[count];
    
        machineGun *a = new machineGun();
        flamer     *b = new flamer();
    
        weapons[0] = a;
        weapons[1] = b;
    
        weapons[0]->fire();
        weapons[1]->fire();
    
        delete a;
        delete b;
    
    }
    

    【讨论】:

    • 这不适用于 OP 的情况,因为派生类中的函数签名与基类不同,因为它使用模板类型。
    【解决方案3】:

    如果您不想更改类的层次结构,可以尝试使用一组可调用对象。比如:

    #include <iostream>
    #include <functional>
    #include <array>
    
    class A
    {
        public:
        void Foo(int a)
        {
            std::cout << "Foo " << a << std::endl;
        }
    };
    
    class B
    {
        public:
        void Bar(int a)
        {
            std::cout << "Bar " << a << std::endl;
        }
    };
    
    int main()
    {
       using namespace std::placeholders;
    
       A a;
       B b;
    
       auto a_func = std::bind(&A::Foo, a, _1);
       auto b_func = std::bind(&B::Bar, b, _1);
    
       std::array<std::function<void(int)>, 2> arr = {
         std::bind(&A::Foo, a, _1),
         std::bind(&B::Bar, b, _1)
       };
    
       arr[0](1);
       arr[1](2);
    
       return 0;
    }
    

    顺便说一句,这仅在您使用完全支持 C++11 的编译器时才有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-05
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 2012-03-05
      相关资源
      最近更新 更多