Confused about casts

P

Paulo da Silva

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.
 
A

Alf P. Steinbach

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! :)
 
P

Paulo da Silva

Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
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
 
P

Paulo da Silva

Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
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
 
A

Alf P. Steinbach

Em 21-12-2011 02:28, Alf P. Steinbach escreveu:
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
 
P

Paulo da Silva

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

Paulo da Silva

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Cannot find my infinite loop 1
Crossword 2
Pseudocode 1
virtual & casting 2
Character operations in C++ 2
[ifstream] Double reading of the last character. 2
Remove Space, Stuck on lab 1
Crossword 14

Members online

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top