Confused about casts

Discussion in 'C++' started by Paulo da Silva, Dec 21, 2011.

  1. Hi,
    Pls. consider the following code:

    using namespace std;

    #include <iostream>
    #include <fstream>

    int main(int argc,char **argv)
    { ifstream *in_p;
    int val;
    if (argc==2)
    { in_p=new ifstream(argv[1]);
    // Test in_p->good()
    }
    else
    in_p=static_cast<ifstream*>(&cin);
    *in_p >> val;
    cout << "val=" << val << endl;
    if (in_p!=&cin)
    delete in_p;
    return 0;
    }

    In the line "in_p=static_cast<ifstream*>(&cin);" both static and
    reinterpret casts seem to work. Which is (more) correct?

    Thanks.
     
    Paulo da Silva, Dec 21, 2011
    #1
    1. Advertising

  2. On 21.12.2011 02:54, Paulo da Silva wrote:
    >
    > using namespace std;
    >
    > #include<iostream>
    > #include<fstream>
    >
    > int main(int argc,char **argv)
    > { ifstream *in_p;
    > int val;
    > if (argc==2)
    > { in_p=new ifstream(argv[1]);
    > // Test in_p->good()
    > }
    > else
    > in_p=static_cast<ifstream*>(&cin);
    > *in_p>> val;
    > cout<< "val="<< val<< endl;
    > if (in_p!=&cin)
    > delete in_p;
    > return 0;
    > }
    >
    > In the line "in_p=static_cast<ifstream*>(&cin);" both static and
    > reinterpret casts seem to work. Which is (more) correct?


    They are both technically allowed, and both are *wrong*.

    static_cast is allowed because ifstream is derived from istream so that
    the opposite direction would convert implicitly.

    reinterpret_cast is allowed because just about any data pointers can be
    reinterpret_cast'ed, although for cases outside the conversions listed
    here and there in the standard the result (and whether it's allowed)
    depends on the compiler and compiler options.

    You're doing a so called *downcast*, to a more derived class.

    That's only proper if the referred to object is of the derived class (or
    more derived).

    Here's what you should do, given the apparent goals of your code:


    <code>
    using namespace std;

    #include <iostream>
    #include <fstream>

    void do_things( istream& in )
    {
    int val;

    in >> val;
    cout << "val=" << val << endl;
    }

    int main( int argc,char *argv[] )
    {
    if (argc==2)
    {
    ifstream f( argv[1] );
    // Test in_p->good()
    do_things( f );
    }
    else
    {
    do_things( cin );
    }
    }
    </code>


    Disclaimer: code untouched by compiler's dirty hands.


    Cheers & hth.,

    - Alf

    PS: I liked your placing "using namespace std;" at the very top. I'll
    start doing that. It's never to late to pick up a good idea! :)
     
    Alf P. Steinbach, Dec 21, 2011
    #2
    1. Advertising

  3. Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
    > On 21.12.2011 02:54, Paulo da Silva wrote:
    >>
    >> using namespace std;
    >>
    >> #include<iostream>
    >> #include<fstream>
    >>
    >> int main(int argc,char **argv)
    >> { ifstream *in_p;
    >> int val;
    >> if (argc==2)
    >> { in_p=new ifstream(argv[1]);
    >> // Test in_p->good()
    >> }
    >> else
    >> in_p=static_cast<ifstream*>(&cin);
    >> *in_p>> val;
    >> cout<< "val="<< val<< endl;
    >> if (in_p!=&cin)
    >> delete in_p;
    >> return 0;
    >> }
    >>
    >> In the line "in_p=static_cast<ifstream*>(&cin);" both static and
    >> reinterpret casts seem to work. Which is (more) correct?

    >
    > They are both technically allowed, and both are *wrong*.
    >
    > static_cast is allowed because ifstream is derived from istream so that
    > the opposite direction would convert implicitly.
    >
    > reinterpret_cast is allowed because just about any data pointers can be
    > reinterpret_cast'ed, although for cases outside the conversions listed
    > here and there in the standard the result (and whether it's allowed)
    > depends on the compiler and compiler options.
    >
    > You're doing a so called *downcast*, to a more derived class.
    >
    > That's only proper if the referred to object is of the derived class (or
    > more derived).
    >
    > Here's what you should do, given the apparent goals of your code:
    >
    >
    > <code>
    > using namespace std;
    >
    > #include <iostream>
    > #include <fstream>
    >
    > void do_things( istream& in )
    > {
    > int val;
    >
    > in >> val;
    > cout << "val=" << val << endl;
    > }
    >
    > int main( int argc,char *argv[] )
    > {
    > if (argc==2)
    > {
    > ifstream f( argv[1] );
    > // Test in_p->good()
    > do_things( f );
    > }
    > else
    > {
    > do_things( cin );
    > }
    > }
    > </code>

    Thanks!
    But using the same logic, may be a little change fixes the problem.
    Isn't this the same?

    <code>
    using namespace std;

    #include <iostream>
    #include <fstream>

    int main(int argc,char **argv)
    { istream *in_p;
    int val;
    if (argc==2)
    { in_p=new ifstream(argv[1]);
    // Test in_p->good()
    }
    else
    in_p=&cin;
    *in_p >> val;
    cout << "val=" << val << endl;
    if (in_p!=&cin)
    delete in_p;
    return 0;
    }
    </code>



    >
    >
    > Disclaimer: code untouched by compiler's dirty hands.
    >
    >
    > Cheers & hth.,
    >
    > - Alf
    >
    > PS: I liked your placing "using namespace std;" at the very top. I'll
    > start doing that. It's never to late to pick up a good idea! :)


    Yes :) For small/medium projects no need for namespaces.
    Thank you
     
    Paulo da Silva, Dec 21, 2011
    #3
  4. Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
    > On 21.12.2011 02:54, Paulo da Silva wrote:
    >>
    >> using namespace std;
    >>
    >> #include<iostream>
    >> #include<fstream>
    >>
    >> int main(int argc,char **argv)
    >> { ifstream *in_p;
    >> int val;
    >> if (argc==2)
    >> { in_p=new ifstream(argv[1]);
    >> // Test in_p->good()
    >> }
    >> else
    >> in_p=static_cast<ifstream*>(&cin);
    >> *in_p>> val;
    >> cout<< "val="<< val<< endl;
    >> if (in_p!=&cin)
    >> delete in_p;
    >> return 0;
    >> }
    >>
    >> In the line "in_p=static_cast<ifstream*>(&cin);" both static and
    >> reinterpret casts seem to work. Which is (more) correct?

    >
    > They are both technically allowed, and both are *wrong*.
    >
    > static_cast is allowed because ifstream is derived from istream so that
    > the opposite direction would convert implicitly.
    >
    > reinterpret_cast is allowed because just about any data pointers can be
    > reinterpret_cast'ed, although for cases outside the conversions listed
    > here and there in the standard the result (and whether it's allowed)
    > depends on the compiler and compiler options.
    >
    > You're doing a so called *downcast*, to a more derived class.
    >
    > That's only proper if the referred to object is of the derived class (or
    > more derived).
    >
    > Here's what you should do, given the apparent goals of your code:
    >
    >
    > <code>
    > using namespace std;
    >
    > #include <iostream>
    > #include <fstream>
    >
    > void do_things( istream& in )
    > {
    > int val;
    >
    > in >> val;
    > cout << "val=" << val << endl;
    > }
    >
    > int main( int argc,char *argv[] )
    > {
    > if (argc==2)
    > {
    > ifstream f( argv[1] );
    > // Test in_p->good()
    > do_things( f );
    > }
    > else
    > {
    > do_things( cin );
    > }
    > }
    > </code>

    Thanks!
    But using the same logic, may be a little change fixes the problem.
    Isn't this the same?

    <code>
    using namespace std;

    #include <iostream>
    #include <fstream>

    int main(int argc,char **argv)
    { istream *in_p;
    int val;
    if (argc==2)
    { in_p=new ifstream(argv[1]);
    // Test in_p->good()
    }
    else
    in_p=&cin;
    *in_p >> val;
    cout << "val=" << val << endl;
    if (in_p!=&cin)
    delete in_p;
    return 0;
    }
    </code>



    >
    >
    > Disclaimer: code untouched by compiler's dirty hands.
    >
    >
    > Cheers & hth.,
    >
    > - Alf
    >
    > PS: I liked your placing "using namespace std;" at the very top. I'll
    > start doing that. It's never to late to pick up a good idea! :)


    Yes :) For small/medium projects no need for namespaces.
    Thank you
     
    Paulo da Silva, Dec 21, 2011
    #4
  5. On 21.12.2011 19:56, Paulo da Silva wrote:
    > Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
    >> On 21.12.2011 02:54, Paulo da Silva wrote:
    >>>
    >>> using namespace std;
    >>>
    >>> #include<iostream>
    >>> #include<fstream>
    >>>
    >>> int main(int argc,char **argv)
    >>> { ifstream *in_p;
    >>> int val;
    >>> if (argc==2)
    >>> { in_p=new ifstream(argv[1]);
    >>> // Test in_p->good()
    >>> }
    >>> else
    >>> in_p=static_cast<ifstream*>(&cin);
    >>> *in_p>> val;
    >>> cout<< "val="<< val<< endl;
    >>> if (in_p!=&cin)
    >>> delete in_p;
    >>> return 0;
    >>> }
    >>>
    >>> In the line "in_p=static_cast<ifstream*>(&cin);" both static and
    >>> reinterpret casts seem to work. Which is (more) correct?

    >>
    >> They are both technically allowed, and both are *wrong*.
    >>
    >> static_cast is allowed because ifstream is derived from istream so that
    >> the opposite direction would convert implicitly.
    >>
    >> reinterpret_cast is allowed because just about any data pointers can be
    >> reinterpret_cast'ed, although for cases outside the conversions listed
    >> here and there in the standard the result (and whether it's allowed)
    >> depends on the compiler and compiler options.
    >>
    >> You're doing a so called *downcast*, to a more derived class.
    >>
    >> That's only proper if the referred to object is of the derived class (or
    >> more derived).
    >>
    >> Here's what you should do, given the apparent goals of your code:
    >>
    >>
    >> <code>
    >> using namespace std;
    >>
    >> #include<iostream>
    >> #include<fstream>
    >>
    >> void do_things( istream& in )
    >> {
    >> int val;
    >>
    >> in>> val;
    >> cout<< "val="<< val<< endl;
    >> }
    >>
    >> int main( int argc,char *argv[] )
    >> {
    >> if (argc==2)
    >> {
    >> ifstream f( argv[1] );
    >> // Test in_p->good()
    >> do_things( f );
    >> }
    >> else
    >> {
    >> do_things( cin );
    >> }
    >> }
    >> </code>

    > Thanks!
    > But using the same logic, may be a little change fixes the problem.
    > Isn't this the same?
    >
    > <code>
    > using namespace std;
    >
    > #include<iostream>
    > #include<fstream>
    >
    > int main(int argc,char **argv)
    > { istream *in_p;
    > int val;
    > if (argc==2)
    > { in_p=new ifstream(argv[1]);
    > // Test in_p->good()
    > }
    > else
    > in_p=&cin;
    > *in_p>> val;
    > cout<< "val="<< val<< endl;
    > if (in_p!=&cin)
    > delete in_p;
    > return 0;
    > }
    > </code>



    Well, it's not quite the same:

    * It uses dynamic allocation, which is generally slow.

    * It's in general not exception safe.

    * At least to my eyes, it's much less clear.

    The problem is that this code addresses many concerns within the same
    little stretch of code.

    Instead, try to separate concerns.


    Cheers & hth.

    - Alf
     
    Alf P. Steinbach, Dec 21, 2011
    #5
  6. Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
    ....

    >
    > Here's what you should do, given the apparent goals of your code:
    >
    >
    > <code>
    > using namespace std;
    >
    > #include <iostream>
    > #include <fstream>
    >
    > void do_things( istream& in )
    > {
    > int val;
    >
    > in >> val;
    > cout << "val=" << val << endl;
    > }
    >
    > int main( int argc,char *argv[] )
    > {
    > if (argc==2)
    > {
    > ifstream f( argv[1] );
    > // Test in_p->good()
    > do_things( f );
    > }
    > else
    > {
    > do_things( cin );
    > }
    > }
    > </code>

    Thanks!
    But using the same logic, may be a little change fixes the problem.
    Isn't this the same?

    <code>
    using namespace std;

    #include <iostream>
    #include <fstream>

    int main(int argc,char **argv)
    { istream *in_p;
    int val;
    if (argc==2)
    { in_p=new ifstream(argv[1]);
    // Test in_p->good()
    }
    else
    in_p=&cin;
    *in_p >> val;
    cout << "val=" << val << endl;
    if (in_p!=&cin)
    delete in_p;
    return 0;
    }
    </code>

    >
    >
    > Disclaimer: code untouched by compiler's dirty hands.
    >
    >
    > Cheers & hth.,
    >
    > - Alf
    >
    > PS: I liked your placing "using namespace std;" at the very top. I'll
    > start doing that. It's never to late to pick up a good idea! :)


    Yes :) For small/medium projects no need for namespaces.
    Thank you
     
    Paulo da Silva, Dec 21, 2011
    #6
  7. Re: Confused about casts (sorry)

    Sorry for the multi posts!!!
    But my News client was informing me that it could not send the posts
    while it was really sending them.

    Thank you
     
    Paulo da Silva, Dec 21, 2011
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?Q2hyaXMgRGF2b2xp?=

    Web casts in ASP.Net

    =?Utf-8?B?Q2hyaXMgRGF2b2xp?=, Oct 19, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    525
    clintonG
    Oct 19, 2005
  2. cgbusch
    Replies:
    2
    Views:
    348
    Sudsy
    Jul 8, 2003
  3. Joona I Palaste

    Needless casts?

    Joona I Palaste, Apr 24, 2004, in forum: Java
    Replies:
    15
    Views:
    714
    Icemerth
    Apr 25, 2004
  4. Dan Upton

    checking casts

    Dan Upton, Nov 29, 2005, in forum: Java
    Replies:
    4
    Views:
    759
    Chris Smith
    Dec 1, 2005
  5. Wenjie

    C++ casts on zero

    Wenjie, Aug 17, 2003, in forum: C++
    Replies:
    11
    Views:
    688
    Wenjie
    Aug 24, 2003
Loading...

Share This Page