在c ++中是否有一种方法可以指向它指向的实际类型?

时间:2014-07-05 08:59:18

标签: c++ casting typeid

编辑。见下文。

考虑以下情况 - 我有一个基类和一些派生类:

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)吗?

2 个答案:

答案 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_auxd1中以不同方式实施d2

[这假设您需要f_aux作为独立函数 - 如果您只需要一个执行此操作的函数,则只需调用虚函数f_aux,然后直接在{{1}中调用它} f]

编辑:

以您描述的方式投射对象是一种“难闻的气味”(http://en.wikipedia.org/wiki/Code_smell) - “你做错了”的症状。使用虚函数几乎总能避免这种情况。