16

Possible Duplicate:
Finding the type of an object in C++

Hello,
I am sorry if it's a duplicate but I was not able to find answer to my question here.
Let's assume we have following class structure in c++:

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
  };

class CRectangle: public CPolygon {
  public:
    int area ()
      { return (width * height); }
  };

Now I have got a pointer to CPolygon object. How do I check if it's actually a pointer to the object of class CRectangle?

Community
  • 1
  • 1
Amit S
  • 1,053
  • 2
  • 9
  • 18
  • 7
    As a side not you should consider not doing that. If you think you need to do it, there is probably something wrong with your design. – Björn Pollex Nov 05 '10 at 15:05
  • 1
    It *always* is. No need to check. Also, *please* don’t prepend your class names with `C`. This was *never* a recommended style and its widespread use is based on a misunderstanding of the MFC naming conventions. – Konrad Rudolph Nov 05 '10 at 15:05
  • 3
    That's not how polymorphism works. Polymorphism means removing the need to check this. –  Nov 05 '10 at 15:08
  • 1
    @Konrad: People are free to choose a naming convention as long as they are consistent with their choice. Your remark is very personal – Armen Tsirunyan Nov 05 '10 at 15:11
  • 6
    There ARE valid reasons to want to know the concrete type of a polymorphic class; that said, they're few and far between. It's good to know how to check the concrete type; it's also good to know that having to do that is usually a bad sign. – Paul Sonier Nov 05 '10 at 15:11
  • 1
    I would dump the `CPolygon` class: the use of `protected` data members is a red herring, but the use of `width` and `height` for a polygon is just plain WRONG. Those data members should be stored in `CRectangle`. – Matthieu M. Nov 05 '10 at 15:14
  • 3
    @Armen: I don't fully agree about the personal bit, as long as you disclose the code it's not personal any longer. Someone will probably inherit from this mess one day or another. – Matthieu M. Nov 05 '10 at 15:15
  • 1
    While the questions are very similar, I don't think this is a duplicate of the question space posted. This question has a visual representationof the problem; the other has a textual description without a clear understanding of the code for those who are weak with the language. I will vote to reopen if this is closed. – San Jacinto Nov 05 '10 at 15:17
  • 1
    @Matthieu: What I mean is there is nothing wrong with a convention of naming classes prefixed with C, Q, X or whatever it is as long as the convention is consistently obeyed. The personal bit regards the fact that if you *don't* like prefixing classes that doesn't mean it's a bad practice – Armen Tsirunyan Nov 05 '10 at 15:17
  • 1
    @Armen: come on, that’s bullshit. There are *technical* reasons for and against choosing a naming convention (as well as personal ones) and there are no good ones for the `C` prefix. And what I said is true: proponents of this convention use it 1) because they were told to, or 2) because they misunderstood why MFC did it. Of course you’re free to prefix your classes with whatever you like, and I am free to tell you that such prefixes serve no purpose, may actually have a negative impact, and to *please use friggin namespaces*. – Konrad Rudolph Nov 05 '10 at 15:28
  • 4
    @Armen: I understand, and I would admit that a one-letter prefix isn't much, but next we'll get `class ClassPolygon;`, `void FunctionAdd(int,int)`, etc... Also, do you prefix `struct` with `C` or `S` ? And what if someone changes the kind but not the prefix ? It may feel personal, but redundancy leads to inconsistency. – Matthieu M. Nov 05 '10 at 15:28
  • @KonradRudolph: production code != example code. I don't disagree with you about naming conventions with production code; however, for a quick sample, it's largely moot. For example, do you really think the OP should have used namespaces for this question? Really? – Paul Sonier Nov 05 '10 at 15:30
  • 2
    @Armen: (cont’d) far too many coding decisions are justified with “don’t argue, it’s a matter of opinions” when in fact it’s not. The MFC introduced the `C` prefix because VC6 had poor namespace support and Microsoft didn’t want the MFC names to clash with other classes. That was misunderstood by many developers who started to copy the convention, thus triggering the exact problems that the MFC had wanted to avoid. Other developers who are beginners in OOP use it to denote classes, not understanding that it’s *meaningless* to distinguish classes from other types: Not a valid usage either. – Konrad Rudolph Nov 05 '10 at 15:32
  • @Matthieu, @Konrad: I hate when people name their classer prefixed with C, believe me, I really do. I also happen to hate hungarian notation. And if I were to choose a coding convention I wouldn't choose any of them. I have my subjective reasons for not liking them, but so do people that do follow those conventions. And believe me many won't even mention MFC... – Armen Tsirunyan Nov 05 '10 at 15:34
  • 1
    @McWafflestix: I don’t believe the OP only used this style in this example, otherwise I wouldn’t have bothered to comment. But since many 1990’s beginners’ books use this abominable style, I find a correction is in order. It’s a form of [cargo cult programming](http://en.wikipedia.org/wiki/Cargo_cult_programming). It should be corrected. – Konrad Rudolph Nov 05 '10 at 15:35
  • @Mathieu: What about Qt? I do believe it was developed by smart and competent people and still they prefix classes with Q. I believe their decision had nothing to do with VB – Armen Tsirunyan Nov 05 '10 at 15:35
  • @Armen: Qt was also probably started at the time when there were no namespaces. Similar for wxWidgets, where each classname is prefixed wx. – UncleBens Nov 05 '10 at 15:46
  • @Armen: That's just an appeal to authority. Just because Trolltech did it doesn't mean it's an acceptable decision. Similarly, I would never recommend that somebody introduce a special preprocessor for their library, as is done for Qt. – Steve M Nov 05 '10 at 15:46
  • @all: This was just an example and thanks for mentioning that starting class names with C is a bad practice. But that's not the issue here. The issue is why is it a bad practice(in terms of design) to know the datatype of a child class? – Amit S Nov 05 '10 at 15:49
  • To continue with the rant... Qt also decided to define macros here and there (some are *somehow required* for their message passing), and they decided to use lower case letters for that. Take as an example `signal`... I don't think anyone can agree on that being a good call, at least not anyone that uses boost intensively and has to use Qt for some projects and suddenly has `boost::signal` being expanded to something else... – David Rodríguez - dribeas Nov 05 '10 at 17:17
  • Or take Google, they have many really good people working there, and yet their C++ coding style guide is quite bad from a C++ standpoint --they have their reasons, but blindly following that guide just because it comes from Google is a perfect example of cargo cult programming. Man, I do love that term! – David Rodríguez - dribeas Nov 05 '10 at 17:17

4 Answers4

16

You can do this by checking if dynamic_cast<CRectangle*>(ptr) return non-null, where ptr is a pointer to CPolygon. However this requires the base class (CPolygon) to have at least one virtual member function which you probably need anyway (at least a virtual destructor).

vitaut
  • 49,672
  • 25
  • 199
  • 336
6

Ideally, you don't. You use polymorphism to just do the right thing:

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }

    virtual int area() const = 0;
  };

class CRectangle: public CPolygon {
  public:
    int area () const
      { return (width * height); }
  };

Call area() on your CPolygon pointer, and you'll get the area for a CRectangle if that's what it is. Everything derived from CPolygon will have to implement area() or you won't be able to instantiate it.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • 14
    That's not what the OP asked, and while it's easy to say "just don't do that", there ARE valid reasons for wanting to get the concrete type of a class. – Paul Sonier Nov 05 '10 at 15:13
  • @McWafflestix: but what if I have another sub class with some extra function in it and I want to call those functions? – Amit S Nov 05 '10 at 15:22
  • @AmitS: that's my point; you might want to do something like that. – Paul Sonier Nov 05 '10 at 15:25
  • @McWafflestix: yes, I get your point now, we can just call any damn function in the whole hierarchy, compiler would automatically detect its type and call the required function. But here is more scenario (and this is what I want to do in this case), what if I don't want to call any function. I just want to check if there is indeed an object of type CRectangle? Is it a valid case or this case should not occur in the design? – Amit S Nov 05 '10 at 15:33
  • @AmitS: I don't think you're responding to my comments, based upon the content of your comments. – Paul Sonier Nov 05 '10 at 15:38
  • 1
    @McWafflestix: I am really sorry, I intended to ask these questions to "Fred Larson". I mixed the names. Sorry for the confusion. @Fred Larson: Would you care to answer the validity of the scenario that I mentioned in my previous comment? – Amit S Nov 05 '10 at 15:42
  • @Amit S: You can use `dynamic_cast`, as vitaut indicated in his answer. But it is a red flag that there may be a problem with your design. – Fred Larson Nov 05 '10 at 15:52
  • 1
    In general it is a sign of bad design having to check the concrete type of an object that is polymorphic. Basically you should avoid it unless really necessary. – David Rodríguez - dribeas Nov 05 '10 at 17:23
4

You can dynamic_cast it:

CRect* pRect = dynamic_cast<CRect*>(MyPolygonPointer);

if(pRect != 0)
{
   //...it is a CRect
}

But naturally downcasting is a bad practice and should be used with caution. In a good design you don't care about the actual dynamic type of the pointer.

Michael0x2a
  • 58,192
  • 30
  • 175
  • 224
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
2

You can perform a dynamic_cast to CRectangle and see if that gives a proper result or not.

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117