编辑。见下文。
考虑以下情况 - 我有一个基类和一些派生类:
class B {...[virtual...]...};
class D1 : public B {...};
class D2 : public B {...};
我有一个函数,假设每个函数都有不同的行为(实现方式。从概念上讲,它们都做同样的事情)。 现在,我当然会为每个实现一个辅助功能:
void f_aux (B * b);
void f_aux (D1 * d1);
void f_aux (D2 * d2);
然后我可以通过这样的方式实现main函数:
void f (B * bd1d2) {
if (typeid(bd1d2) == typeid(B*) { f_aux((B*)bd1d2); }
else if (typeid(bd1d2) == typeid(D1*) { f_aux((D1*)bd1d2); }
else if (typeid(bd1d2) == typeid(D2*) { f_aux((D2*)bd1d2); }
}
现在,我的问题是 - 我能否以一般方式执行此操作,意思是:
void f (B * bd1d2) {
f_aux(CAST_TO_REAL_TYPE(bd1d2));
}
我尝试直接使用typeid当然失败了。 我尝试在线搜索,没有任何结果......
所以,有没有办法做到这一点?如果没有,那么为什么?
非常感谢..修改:
我试图简化问题,似乎我做了相反的事情。 让我再尝试一次 : 在实际设置中,我有3个类:Line,Ray和Segment,我想要另一个类(Graph-Edge)来保存任何类型的对象的通用指针 - 意思是,它有一个字段可以是Line Ray或Segment。 现在,我想选择获得2个Graph-Edges或Graph-Edge与给定Line / Ray / Segment的交叉点,而不处理“这是什么样的边缘? “两个都没有。 我也希望我的Geometry类尽可能通用,即使Graph-Edges中没有必要使用某些功能。 所以我创建了一个超类:LinearObject,带有一个虚拟的getCut(LinearObject& lo)函数,并按照下面的答案,到目前为止我得到的最好的是:
class Line;
class Segment;
class LinearObject {
public :
virtual void getCut(LinearObject * lo) { printf("lo->lo\n"); }
private :
virtual void getCut_aux(Line * l) = 0;
virtual void getCut_aux(Segment * s) = 0;
friend class Line; friend class Segment;
};
class Line : public LinearObject {
public :
void getCut(LinearObject * lo) { printf("l->lo\n"); lo->getCut_aux(this); }
private :
void getCut_aux(Line * l) { printf("l->l\n"); }
void getCut_aux(Segment * s) { printf("l->s\n"); }
};
class Segment : public LinearObject {
public :
void getCut(LinearObject * lo) {
printf("s->lo\n");
lo->getCut_aux(this);
}
private :
void getCut_aux(Line * l) { printf("s->l\n"); }
void getCut_aux(Segment * s) { printf("s->s\n"); }
};
int main() {
Line l; Segment s;
LinearObject *lop = &l, *lop2 = &s;
lop->getCut(lop2);
s.getCut(&l);
return 0;
}
它有效,但是,我可以做得更好(Eleganltly)吗?
答案 0 :(得分:3)
编辑:在编辑问题后进行编辑,希望我理解您想要的一切......
#include <cstdio>
class Line;
class Segment;
class LinearObject {
protected :
virtual void getCut_aux(LinearObject *) { printf("LinearObject->getCut_aux\n") ; }
friend class LinearObject_ ;
};
class LinearObject_ : public LinearObject {
public:
void getCut (LinearObject * lo) { printf("getCut()\n"); lo->getCut_aux(this) ; }
};
class Line : public LinearObject_ {
protected :
virtual void getCut_aux(LinearObject *) { printf("Line->getCut_aux\n") ; }
};
class Segment : public LinearObject_ {
protected:
virtual void getCut_aux(LinearObject *) { printf("Segment->getCut_aux\n") ; }
};
int main() {
Line l; Segment s;
LinearObject *lop = &l, *lop2 = &s;
l.getCut(lop2);
s.getCut(&l);
return 0;
}
编辑结束。
如果你可以在类中实现f_aux
,只需利用多态:
class B {
/* ...[virtual...]... */
virtual void f_aux () { /* ... */ }
};
class D1 : public B {
/* ... */
virtual void f_aux () { /* ... */ }
};
class D2 : public B {
/* ... */
virtual void f_aux () { /* ... */ }
};
然后就这样做:
void f (B * bd1d2) {
bd1d2->f_aux () ; // Will call the correct function depending on what bd1d2 points to
}
修改:要回答您的评论,如果您想要d->f_aux(b)
之类的内容,只需添加一个中间类D
:
class D {
void f (B *b) { b->f_aux(this) ; }
};
class D1 : public B, public D { /* ... */ };
B *pdb = new B (), *pd3 = new D3 () ;
D1 *pd1 = new D1 () ;
D2 *pd2 = new D2 () ;
pd1->f(b) ;
pd2->f(pd3) ;
答案 1 :(得分:2)
对此的“正确”解决方案是使用虚拟函数:
void f_aux (B * b)
{
b->do_f_aux();
}
您将do_f_aux
声明为
class B
{
...
virtual void do_f_aux() { ... };
}
当然在do_f_aux
和d1
中以不同方式实施d2
。
[这假设您需要f_aux
作为独立函数 - 如果您只需要一个执行此操作的函数,则只需调用虚函数f_aux
,然后直接在{{1}中调用它} f
]
编辑:
以您描述的方式投射对象是一种“难闻的气味”(http://en.wikipedia.org/wiki/Code_smell) - “你做错了”的症状。使用虚函数几乎总能避免这种情况。