我有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,它只调用那个方法。
答案 0 :(得分: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
放入Foo / A / B / C,那么您可能需要查看访问者设计模式:
答案 1 :(得分: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();
}
答案 2 :(得分: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 */ };
};
然后在指向Foo
的指针上调用someMethod将自动从相应的类调用该方法。如果无法做到这一点,因为someMethod
无法作为Foo
或其衍生物的一部分实现(例如,它需要访问当前在您的设计中的类的私有成员),那么您可能会尝试将此功能拆分为可以放入这些类的虚拟方法的子问题A
B
C
。
2)“我没有选择”的方式:
使用RTTI(运行时类型识别),它包含在C ++中。它要求您的基类Foo至少有一个虚方法。您需要#include <typeinfo>
,然后在指针上使用typeid(),它将返回type_info对象,您可以将其name()
结果与类名称{{1}进行比较} A
和B
。这不是一个非常好的方法,因为它有更多的开销,它打破了OOP设计原则。但如果这是唯一的选择,那就没关系。
答案 3 :(得分:0)
RTTI是你的朋友。链接中给出的示例将指导您进一步
答案 4 :(得分:-1)
您可以将子类的方法作为成员方法调用。例如,A a = new A(); a.some_method()
应该调用正确的方法。在some_method()中,您可以使用关键字this引用对象。