Thread: How would I achieve this dynamic_cast?

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    184

    How would I achieve this dynamic_cast?

    Code:
    (I am not the one who defined these classes)
    
    class _jobject {};
    class _jarray : public _jobject {};
    
    typedef _jobject* jobject;
    typedef _jarray* jarray;
    
    int main()
    {
         jobject * a;
         jarray b;
         a = dynamic_cast<jobject*> (&b);
    ....
    }
    This doesn't work and the problem is the only type names I'm guaranteed to have are jobject and jarray. The original _jobject is how it's defined here but I'm not guaranteed it''ll always be that way so I have to work with jobject/jarray.

    This works at runtime:
    Code:
    jobject a;
    jarray b;
    a = ( jobject ) b;
    So why doesn't the dynamic cast?

    How would I cast between jobject and jarray (and other types if coming in, I only know it's of type <some_sub-Type>?
    Last edited by 6tr6tr; 04-13-2008 at 12:56 PM.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    How would I cast between jobject and jarray?
    Well, you can, but I'm not going to tell you how. It would lead, with those 'typedef's, to undefined behavior. (One is a pointer to an object and one is an object.)

    Personally, I'm hoping that you've simply barfed on the example. You can assign a pointer to a derived class directly to a pointer to a base class with no cast. (I'm assuming you missed the '*' in the 'typedef'.)

    Code:
    class _jobject {};
    class _jarray : public _jobject {};
    
    typedef _jobject jobject;
    typedef _jarray jarray;
    
    int main()
    {
         jobject * a;
         jarray b;
         a = &b;
    }
    Soma

  3. #3
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by phantomotap View Post
    Well, you can, but I'm not going to tell you how. It would lead, with those 'typedef's, to undefined behavior. (One is a pointer to an object and one is an object.)

    Personally, I'm hoping that you've simply barfed on the example. You can assign a pointer to a derived class directly to a pointer to a base class with no cast. (I'm assuming you missed the '*' in the 'typedef'.)

    Code:
    class _jobject {};
    class _jarray : public _jobject {};
    
    typedef _jobject jobject;
    typedef _jarray jarray;
    
    int main()
    {
         jobject * a;
         jarray b;
         a = &b;
    }
    Soma

    Sorry, the correct defs:
    Code:
    class _jobject {};
    class _jarray : public _jobject {};
    
    typedef _jobject* jobject;
    typedef _jarray* jarray;
    So why doesn't the dynamic_cast work (why isn't it allowed)?

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    typedef _jobject* jobject;
    typedef _jarray* jarray;
    Stuff like that drives you mad when reading others code. Don't do it.
    Use proper types instead:
    Code:
    class _jobject {};
    class _jarray : public _jobject {};
    
    int main()
    {
         _jobject** a;
         _jarray* b;
         a = dynamic_cast<_jobject**> (&b);
    ....
    }
    And from what I understand, you cannot implicitly convert a pointer to pointer of a derived class to base.
    This also fails:

    Code:
    class _jobject {};
    class _jarray : public _jobject {};
    
    int main()
    {
         _jobject** a;
         _jarray* b;
         a = &b;
    ....
    }
    To get around it, you can use an explicit C-style cast or a static cast to get it to compile:

    Code:
    class _jobject {};
    class _jarray : public _jobject {};
    
    int main()
    {
         _jobject** a;
         _jarray* b;
         a = static_cast<_jobject**> (&b);
    ....
    }
    But, perhaps better is to convert the derived pointer to a base pointer first and then assign its address to the base object pointer:

    Code:
    class jobject {};
    class jarray : public jobject {};
    
    int main()
    {
    	jobject** a;
    	jarray* b;
    	jobject* temp = b;
    	a = &temp;
    	return 0;
    }
    Last edited by Elysia; 04-13-2008 at 02:22 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Code:
    class jobject {};
    class jarray : public jobject {};
    
    int main()
    {
    	jobject** a;
    	jarray* b;
    	jobject* temp = b;
    	a = &temp;
    	return 0;
    }
    This is the only correct way to do this. (If 'b' was a parameter to a '__fastcall' function, for example, the 'static_cast' approach would end the universe.)

    So why doesn't the dynamic_cast work (why isn't it allowed)?
    Well, basically, the same reason it doesn't work for this other code.

    Code:
    int main()
    {
    	int ** a;
    	double * b;
    	a = dynamic_cast<int **>(&b);
    	return 0;
    }
    Code:
    struct base_a{};
    struct base_b{};
    
    int main()
    {
    	base_a ** a;
    	base_b * b;
    	a = dynamic_cast<base_a **>(&b);
    	return 0;
    }
    In your code, because the vanilla types, the classes, are related by inheritance it disguises the issue. One way or the other, it is only classes, or rather instances, that behave polymorphically; pointers, even pointers to polymorphic types do not behave polymorphically. (They only point to an instance, presumably, which behaves polymorphically--hence the implicit cast policy.)

    Soma

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Elysia, he didn't define those types. They are part of the Java Native Interface headers, and he has zero control over them.

    The correct form of the dynamic_cast, if it were allowed at all, would be
    Code:
    jobject o = whatever;
    jarray a = dynamic_cast<jarray>(o);
    That said, since _jobject doesn't have any virtual functions, you can't do that.

    If you already know that you're dealing with an array, you can just static_cast the thing:
    Code:
    jarray a = static_cast<jarray>(o);
    If you don't know that, you'll have to test it. And that's not pretty. Actually, I have no idea how to do it. I don't know how to get the jclass for generic arrays, or even if there is such a thing.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by CornedBee View Post
    Elysia, he didn't define those types. They are part of the Java Native Interface headers, and he has zero control over them.
    That does not mean you need or must use them. Avoid them if possible.
    The darn things confused me twice when reading the code. That should say plenty.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Aren't names beginning with an underscore supposed to be reserved for the compiler?

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Not all of them. I believe it's all names beginning with an underscore in the global scope, all names with a double underscore in any scope, and all names with an underscore followed by a capital letter. The relevant standard text has been posted here a few times, but I'm too lazy to look it up.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    But yes, jni is in violation of these rules by defining global names starting with an underscore.

    So is the xorg code. So is the Linux kernel code, I believe. And I have no doubt that you'll quickly find dozens of other projects that have the same problem.

    That poor rule must be the most-ignored one in the C standard.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by CornedBee View Post
    That poor rule must be the most-ignored one in the C standard.
    To be fair, the actual rule allows names beginning with a single underscore followed by a lower-case letter. In C, at least -- I don't know about C++.

    Having said that, I find the rule almost tyrannical. They could have simply reserved all names beginning with a double underscore, and allowed everybody else to use the underscore just like they do -- to indicate that a name is part of internal implementation details.

    It seems like the motivation was entirely backwards. It gives the standard library creators an easy way to "protect" internal symbols and at the same time screws the actual users of the language into inventing goofy ways of doing the same thing. I hate it, honestly.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Having said that, I find the rule almost tyrannical. They could have simply reserved all names beginning with a double underscore, and allowed everybody else to use the underscore just like they do -- to indicate that a name is part of internal implementation details.

    It seems like the motivation was entirely backwards. It gives the standard library creators an easy way to "protect" internal symbols and at the same time screws the actual users of the language into inventing goofy ways of doing the same thing. I hate it, honestly.
    There is no rule against adding an underscore to the end of any identifier (that does not already end with an underscore) in any scope.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Quote Originally Posted by Elysia View Post
    That does not mean you need or must use them. Avoid them if possible.
    The darn things confused me twice when reading the code. That should say plenty.
    I agree with you to an extent, however its best programming practice to conform to the API in which you are using to write your code. For example, some people like var_names_like_this, while others prefer variables_named_like_this, while still others like VariablesNamedLikeThis, and of course, there are the ones who like varsNamedLikeThis or any other imaginable variations.

    The point is, if I use an API that you wrote, where you define things using a specific naming convention or even stupid typedefs that I can't fathom why you opted to use them, instead of being rebellious, its a good idea to just bite the bullet and conform. Afterall, one day someone else may have read your rebelious code

  14. #14
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by master5001 View Post
    I agree with you to an extent, however its best programming practice to conform to the API in which you are using to write your code. For example, some people like var_names_like_this, while others prefer variables_named_like_this, while still others like VariablesNamedLikeThis, and of course, there are the ones who like varsNamedLikeThis or any other imaginable variations.

    The point is, if I use an API that you wrote, where you define things using a specific naming convention or even stupid typedefs that I can't fathom why you opted to use them, instead of being rebellious, its a good idea to just bite the bullet and conform. Afterall, one day someone else may have read your rebelious code
    Kind of like Windows with its billions of typedefs for DWORD, LPSTR, LPCSTR, LP...

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Which is another good thing to avoid, I think.
    In my mindset, if there's a reason to break the rule, then do so. Code readability in this case is more important than consistency.
    Likewise, if a project has really poor indentation, would you copy that indentation to keep it consistent when writing new code? I'd break it.
    Consistency should be uphold, but there is a fine line somewhere.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 10-31-2008, 01:26 PM
  2. Best way to achieve this
    By cloudy in forum Networking/Device Communication
    Replies: 1
    Last Post: 09-06-2006, 07:23 PM
  3. Replies: 3
    Last Post: 09-11-2005, 10:13 AM
  4. The more intelligent risks you take in life, the more you'll achieve
    By Terrance in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 05-20-2003, 05:23 PM