Function returning a "null" reference object

P

Pablo J Royo

Hello:

i have a function that reads a file as an argument and returns a reference
to an object that contains some information obtained from the file: FData
&ReadFile(string FilePath);

But , for example, when the file doesnt exists, i should not return any
reference to a bad constructed object, so i need something as a NULL
reference object. I suppose i could return a pointer instead, but i have
some code written with references which I´d like to preserve...
¿How can i do that?
 
A

Attila Feher

Pablo said:
Hello:

i have a function that reads a file as an argument and returns a
reference to an object that contains some information obtained from
the file: FData &ReadFile(string FilePath);

But , for example, when the file doesnt exists, i should not return
any reference to a bad constructed object, so i need something as a
NULL reference object. I suppose i could return a pointer instead,
but i have some code written with references which I´d like to
preserve...

You can throw an exception.

BTW how do you return that reference? What does it refer to? I hope not an
automatic variable.
¿How can i do that?

No need for that upside down question mark. :)
 
P

Pablo J Royo

Thanks for your response.
I had an object allocated with new inside the function (FData *pData =
new...) , and i returned its contents (return *pData) but this gave me all
kind of problems when i put the returned object in a STL vector container,
so in fact I changed my declaration to be

FData &ParseFileTags(FData &Ret,char *path)

If all goes well, Ret contains good data after this call and i return that
same object. If not, I dont want to return a reference to that object, but
to another "NULL" object instead, or something that allows me to write

result = ParseFileTags(Ret,path);
if (result == NULL)
....
else
.....

I would prefer not to use exceptions, but as i write this i realize it may
be the only true solution...
 
F

Frank Schmitt

Pablo J Royo said:
Hello:

i have a function that reads a file as an argument and returns a reference
to an object that contains some information obtained from the file: FData
&ReadFile(string FilePath);

Make that FData& ReadFile(const string& FilePath).
I'm curious - why are you returning by reference? Is this some static data
in ReadFile()?
But , for example, when the file doesnt exists, i should not return any
reference to a bad constructed object, so i need something as a NULL
reference object. I suppose i could return a pointer instead, but i have
some code written with references which I´d like to preserve...
¿How can i do that?

Depending on whether you can change the signature of ReadFile() and/or
what you want to do in case of error, you have (at least) the following
possibilities:

- add a flag to ReadFile() that indicates whether the read was successfull
i.e. FData& ReadFile (const string& FilePath, bool& Success)
or even bool ReadFile(const string& FilePath, FData& Data)
- throw an exception in case of failure, and handle it in the caller
- implement the NullObject Pattern (see "Refactoring", Fowler et al); in
short, derive a class NullFData from FData, implement the necessary
member functions as doing nothing or returning default values, and
return a NullFData from ReadFile() if the file doesn't exist

HTH & kind regards
frank
 
A

Attila Feher

Pablo J Royo wrote:

PLEASE do not top post and SNIP!

http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.4

Thanx.
Thanks for your response.
I had an object allocated with new inside the function (FData *pData =
new...) , and i returned its contents (return *pData) but this gave
me all kind of problems when i put the returned object in a STL
vector container, so in fact I changed my declaration to be

FData &ParseFileTags(FData &Ret,char *path)

That is a memory leak waiting to happen. Instead of a reference return a
smart pointer. Something like the boost one.

What you do is you are making trial and error to hide your missing knowledge
about new/delete and containers. Not a good think. Have you ever tried to
find out what were those "weird things" with the vector and most importantly
*why*? What you have made here is a program, which will eat up its
resources.
If all goes well, Ret contains good data after this call and i return
that same object. If not, I dont want to return a reference to that
object, but to another "NULL" object instead, or something that
allows me to write

result = ParseFileTags(Ret,path);
if (result == NULL)
...
else
....

I would prefer not to use exceptions, but as i write this i realize
it may be the only true solution...
[SNIP]

Not necessarily. You can return a boost::shared_ptr or something like that
and check if it has a valid pointer inside. IIRC it goes exactly like with
a normal pointer.
 
G

Gavin Deane

FData &ParseFileTags(FData &Ret,char *path)

If all goes well, Ret contains good data after this call and i return that
same object. If not, I dont want to return a reference to that object, but
to another "NULL" object instead, or something that allows me to write

result = ParseFileTags(Ret,path);
if (result == NULL)
...
else
....

I would prefer not to use exceptions, but as i write this i realize it may
be the only true solution...

You can't have a null reference. That's one of the reasons for
choosing references over pointers in some circumstances. If you want
to return a reference, you'll need to decide what object 'result' will
refer to after the function call if ParseFileTags fails.

GJD
 
J

Jerry Coffin

royop@tb- said:
Hello:

i have a function that reads a file as an argument and returns a reference
to an object that contains some information obtained from the file: FData
&ReadFile(string FilePath);

But , for example, when the file doesnt exists, i should not return any
reference to a bad constructed object, so i need something as a NULL
reference object. I suppose i could return a pointer instead, but i have
some code written with references which I´d like to preserve...

You have a number of choices. First of all, I have to wonder why you're
returning a reference at all -- almost the only time you want a function
to return a reference is when it's returning a reference to an object
that was passed to it as a parameter (e.g. operator= return *this, or
operator<< or operator>> returning a reference to the stream in which it
was invoked).

If you insist on doing this anyway, one possibility is to create a
static instance of an object and return a reference to it when you need
a null object:

class FData {
public:
static FData null_object;
// ...
};

FData::null_object;

FData &ReadFile(string const &FilePath) {
// I know access isn't portable, but hopefully I can get away with it as
// filling, so to speak.
if ( !access(FilePath.c_str(), 0))
return FData::null_object;
// ...
}

Using this implicitly assumes that the object in question is relatively
small -- if an object takes up a lots of space, you probably don't want
to create one just to use as a null object. This allows you to use
references, but having introduced the possibility of a null object being
returned, your code usually has to be written a lot like if you used
pointers -- instead of 'if ( returned_value == NULL)', you use something
like 'if (&returned_value == &FData::null_object)', but the basic form
of the code becomes almost like you used pointers.

You've already mentioned the possibility of using pointers, and (more or
less) rejected it.

Another possibility would be for ReadData to throw an exception if it
can't do what it's been asked to. Normally I wouldn't suggest this for
dealing with a situation like a missing file, but if it allows you to
write the rest of your code a lot more cleanly, it may be justified.
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top