2011-02-04 68 views
2

我有一个Foo对象的链表。 Foo是一个基类,它有几个继承自它的类。说,类A, B, and C找出继承对象的类

我正在通过这个链表进行循环,并调用方法some_method,它有3个定义;一个用于每个子类:

some_method(A a); 
some_method(B b); 
some_method(C c); 

链表是通用的,所以它是Foo型的,因为它有A,B和C的对象的分类。

当我通过链接列表current_element骑自行车,打电话some_method(current_element);,我该如何使它调用正确的方法?编译器抱怨说,直到我写了一个采用通用Foo的some_method,并且它只调用该方法。

回答

3

根据您的要求,您可能需要考虑使用多态性。为此,请将纯虚拟方法添加到基节点类中,并将相应的方法移至派生类。

class Foo 
{ 
public: 
    virtual void some_method() = 0; 
}; 

class A : Foo 
{ 
public 
    virtual void some_method() 
    { 
    // move the body of some_method(A a) here 
    } 
}; 

对于这个工作,你的链接列表将需要Foo*,而不是Foo

class Node 
{ 
public: 
    Foo* foo; 
    Node* next; 
}; 

// ... 

Node* someNode = GetNode(); 
// Calls correct method - A::some_method, B::some_method, or C::some_method 
someNode->foo->some_method(); 

如果你不能把some_method在富/ A/B/C,那么你可能要考虑Visitor设计模式:

http://en.wikipedia.org/wiki/Visitor_pattern

+0

这听起来很正确,但是Foo没有有权访问some_method,它将作为参数传递给方法。它位于一个具有Foo指针链接列表的类中,作为数据成员 – bandai 2011-02-04 04:48:36

0

RTTI是你的朋友在这里。链接中给出的示例将进一步引导您

+0

我只使用RTTI作为最后的手段。如果我绝对不能修改`Foo`,那最后的办法是。如果有一个例子,而不仅仅是一个链接,会upvote。 – 2011-02-04 04:57:55

-1

您可以将子类的方法作为成员方法调用。例如A a = new A(); a.some_method()应该调用正确的方法。在some_method()内,您可以使用关键字this来引用对象。

+0

也许我是误解,但这似乎并不会奏效。我想我应该澄清; A是链接列表存储位置的数据成员。一个对象不能访问some_method。 some_method是用一个A对象作为参数调用的 – bandai 2011-02-04 04:43:55

+0

对不起,我误解了,当你说“每个孩子一个班”时我想我认为你的意思是每个班都包含一个some_method()定义 – 2011-02-04 07:19:10

1

两种方式:

1)更好的方法:

颠倒你的设计,使someMethod是基类Foo的虚拟方法,并在派生类中重新定义它。正如:

class Foo { 
    public: 
     virtual void someMethod() = 0; 
}; 

class A { 
    public: 
     void someMethod() { /* implementation specific to A here */ }; 
}; 

class B { 
    public: 
     void someMethod() { /* implementation specific to B here */ }; 
}; 

class C { 
    public: 
     void someMethod() { /* implementation specific to C here */ }; 
}; 

然后调用上的指针的someMethod到Foo会自动调用从相应的类中的方法。如果由于someMethod无法作为Foo或其衍生产品的一部分(例如它需要访问当前在您设计中的类的私有成员)的一部分而无法实现,那么您可能会尝试将此功能拆分为子问题被放入这些类别的虚拟方法中ABC

2)“我没有选择”的方式:

使用RTTI(运行时类型识别),它包含在C++。它要求你的基类Foo至少有一个虚拟方法。您需要#include <typeinfo>,然后在指针上使用typeid(),它将返回一个type_info对象,并且您可以将其name()结果与类名称ABC进行比较。这不是一个很好的方法,因为它有更多的开销,并且破坏了OOP设计原则。但如果这是唯一的选择,那很好。

2

这是“双派”问题。您可以使用访问者模式。通常访问者是基类,所以你可以重复使用这个设计来解决多个问题。

#include <iostream> 
class FooVisitor; 

class Foo 
{ 
public: 
    virtual void some_method() = 0; 
    virtual void visit(FooVisitor* v) = 0; 
}; 

class A; 
class B; 
class FooVisitor 
{ 
public: 
    virtual void visit(A* a){ std::cout << "A" << std::endl;} 
    virtual void visit(B* b){std::cout << "B" << std::endl;} 
}; 

class A : public Foo 
{ 
public: 
     virtual void some_method() 
    { 
     // move the body of some_method(A a) here 
    } 
    virtual void visit(FooVisitor* v) { v->visit(this);} 
}; 

class B : public Foo 
{ 
public: 
     virtual void some_method() 
    { 
     // move the body of some_method(A a) here 
    } 
    virtual void visit(FooVisitor* v) { v->visit(this);} 
}; 

int main() 
{ 
    FooVisitor fv; 
    Foo* f1 = new A; 
    f1->visit(&fv); 
    Foo* f2 = new B; 
    f2->visit(&fv); 
    getchar(); 
}