1

我正在尝试解决以下问题。我有一个指向自定义类的指针的向量(它实际上是一个自定义结构,但一个向量足以替代这个问题)A。类A实际上可以存储一个type_a指针或一个type_b指针(这些类型完全不同并且彼此不相关)。现在这是通过保留两者来实现的,将它们设置为NULL,然后稍后有一堆if/else语句来检查它是哪种类型并执行适当的操作。

class A {
public:
  A() : p1(NULL), p2(NULL) {}

  type_a * p1;
  type_b * p2;
};

std::vector<A *> v;

...

if (v[0]->p1 != NULL) { /* do this */ }
else if (v[0]->p2 != NULL) { /* do that */ }

我计划添加更多指向 class的指针A,因此上述内容开始变得麻烦。我目前正在尝试使用的解决方案是boost::variant

class A {
public:
  boost::variant<type_a*, type_b*> p;
};

不过,我遇到的问题是,我的一项操作涉及调用一个函数,该函数将根据p我拥有的类型为变量分配一些值。这就是现在的情况,并且process_stuff在上述if/else语句之一中调用了适当的函数:

class B { /*...*/ };

void process_stuff(type_a * p, B * b) {
  b->m_var = p->fn1();
}

void process_stuff(type_b * p, B * b) {
  b->m_var = p->fn2();
}

我无法使用它,boost::static_visitor因为(据我所知)我不能有一个非变体类型作为二进制访问中的参数,也不能有一个非常量operator()来使第二个变量成为访问者类并通过operator()一元访问对其进行修改。所以我很困惑如何将上述process_stuff功能转换为与boost::variant.

顺便说一句,我不依附boost::variant并会采取其他解决方案。

4

2 回答 2

4

你只需要一个有状态的访问者。我是根据对访问者长相的模糊记忆来输入这个的,但你应该能够纠正我犯的任何错误。

class process_stuff_visitor : public boost::static_visitor<void> {
  B* m_b;

public:
  process_stuff_visitor(B* b) : m_b(b) {}
  void visit(type_a* a) const { m_b->m_var = a->fn1(); }
  void visit(type_b* b) const { m_b->m_var = b->fn2(); }
};
// actual processing:
boost::apply_visitor(v[0], process_stuff_visitor(the_b));

或者,由于您分配给 B 的同一成员,您可以只提取值生成部分。

struct generate_stuff_visitor : public boost::static_visitor<TypeOfMVar> {
  TypeOfMVar visit(type_a* a) const { return a->fn1(); }
  TypeOfMVar visit(type_b* b) const { return b->fn2(); }
};
the_b->m_var = boost::apply_visitor(v[0], generate_stuff_visitor());
于 2013-06-26T17:21:19.890 回答
0

一种非常通用的面向对象的方式来做你想做的事情(如果我理解正确的话)是为类型 a 和 b(以及你想要的任何其他类型)创建一个虚拟基类,它定义了一个纯虚拟方法。此方法将为每种类型返回不同的内容(例如,type_b::method 可能返回 'b',而 type_a::method 可能返回 'a'),因此当您在未指定类型上调用该方法时,您会被告知它是什么类型。

从那里,您可以使用标识方法的返回值作为 switch 语句的主题,或使用其他一些常规控制结构来调用正确的行为。

于 2013-06-26T17:10:24.173 回答