2013-06-26 79 views
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 */ } 

我计划更多的指针添加到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工作(据我所知)我不能在二进制访问中有一个非变量类型作为参数,我也不能有一个非const operator()使第二个变量成为访问者类的成员并使用一元访问修改operator()的内部变量。所以我很困惑如何将上面的process_stuff函数与boost::variant一起玩。

顺便说一句我没有附加到boost::variant并会采取其他解决方案。

+0

简短的回答:除非你可以以某种方式统一类型,否则任何你做异构集合的方式,它可能会变得丑陋和笨拙。 –

+0

我不能统一类型不幸的。我认为如果我能够做到这一点,这一切都会奏效。在'static_visitor'中有一个非const'operator()'。 – eddi

回答

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

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

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

+0

谢谢,但'type_a'和'type_b'是“上帝赐予”的,所以我无法控制它们。 – eddi

+0

啊,在这种情况下,我会同意杰里科芬对情况的评估。 – CosmicComputer