简体   繁体   English

在c + +中有一种方法可以将指针转换为它所指向的实际类型?

[英]is there a way in c++ to cast a pointer to the real type it points to?

Edited. 编辑。 see below. 见下文。

Consider the following situation - I have a base class and some derived ones : 考虑以下情况-我有一个基类和一些派生类:

class B {...[virtual...]...};

class D1 : public B {...};

class D2 : public B {...};

and I have a function that suppose to behave differently on each of them (implement-wise. conceptually, they all do the same thing). 并且我有一个函数,假定它们在每个函数上的行为都不同(从实现角度来看,从概念上讲,它们都做同样的事情)。 now, I would of course implement an auxiliary function for each : 现在,我当然会为每个实现一个辅助功能:

void f_aux (B * b);
void f_aux (D1 * d1);
void f_aux (D2 * d2);

and then I can implement the main function by doing something like this : 然后我可以通过执行以下操作来实现主要功能:

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); }
}    

now, my question is - can I do this in a general way, meaning something like : 现在,我的问题是-我能以一般方式执行此操作吗,意思是:

void f (B * bd1d2) {
       f_aux(CAST_TO_REAL_TYPE(bd1d2));
}    

I tried using typeid directly which of course failed. 我尝试直接使用typeid当然失败了。 I tried searching that online and nothing came up.. 我尝试在网上搜索,但没有任何反应。

so, Is there a way of doing it? 所以,有办法吗? and if there isn't, than why? 如果没有,那为什么呢?

many thanks.. 非常感谢..

Edit : 编辑:

I tried to simplify the problem, and it seems that I've done the opposite.. Let me try again : In the real settings, I have 3 classes : Line, Ray and Segment, and I'd like another class (a Graph-Edge) to hold a general pointer to an object any of the types - meaning, it has a field that can be either Line Ray or Segment. 我试图简化问题,似乎我做了相反的事情。让我再试一次:在实际设置中,我有3个类:Line,Ray和Segment,我想要另一个类(一个Graph -Edge)以保存指向任何类型对象的通用指针-表示该对象的字段可以是Line Ray或Segment。 Now, I'd like to have the option to get an intersection point of 2 Graph-Edges, or of a Graph-Edge with a given Line/Ray/Segment without dealing with the question of "what kind of an edge is this?" 现在,我想选择获取2个Graph-Edges的交点,或获得具有给定Line / Ray / Segment的Graph-Edge的交点,而无需处理“这是哪种边缘? “ on none of the two. 两者都不是。 I would also like to have my Geometry classes as generic as possible, even if some of the functionality is not necessary in Graph-Edges.. So I made a super-class : LinearObject, with a virtual getCut(LinearObject & lo) function, and followed the answers below, and the best I've got so far is this : 我还希望我的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;
}

It works, but, can I do any better (Eleganltly) ? 它有效,但是,我能做得更好吗?

Edit: Edit after you question edit, hope I understand everything you want... 编辑:在您提出问题后进行编辑,希望我了解您想要的一切...

#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;
}

End of edit. 编辑结束。

If you can implement f_aux inside the class, just take advantage of polymorphism: 如果可以在类内部实现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 () { /* ... */ } 
};

Then just do: 然后做:

void f (B * bd1d2) {
    bd1d2->f_aux () ; // Will call the correct function depending on what bd1d2 points to
}

Edit: To answer your comment, if you want to have something like d->f_aux(b) just add an intermediate class D : 编辑:要回答您的评论,如果您想拥有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) ;

The "correct" solution for this is to do something like is to use virtual functions: 为此,“正确”的解决方案是使用虚函数:

void f_aux (B * b)
{
  b->do_f_aux();
}

where you declare do_f_aux as 您将do_f_aux声明为

class B 
{
 ... 
 virtual void do_f_aux() { ... }; 
}

and of course implement the do_f_aux differently in d1 and d2 . 并且当然在d1d2 do_f_aux不同的方式实现do_f_aux

[This assumes you need f_aux as a standalone function - if you just need a function that does this, then just call the virtual function f_aux , and call it directly in the f as bd1d2->f_aux() ] [这假设您需要f_aux作为独立函数-如果您只需要一个执行此功能的函数,则只需调用虚拟函数f_aux ,并直接在f bd1d2->f_aux()其作为bd1d2->f_aux()调用]

Edit: 编辑:

Casting objects in the way you describe is a "bad smell" ( http://en.wikipedia.org/wiki/Code_smell ) - a symptom of "you're doing it wrong". 以您描述的方式投射对象是一种“难闻的气味”( http://en.wikipedia.org/wiki/Code_smell)-一种“您做错了”的症状。 It can almost always be avoided by using virtual functions. 使用虚函数几乎总是可以避免这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM