C++ Best practices, OOD, Linked List

2

2005

Hi

In C++, are the following considered best practices or not?
- passing aguments to functions (ie functions do not take any arguments
)
- returning values using return statement

Anything else?

The reason for this question is that I had an assignment in which I was
asked to modify so that the main will call all the functions from main
itself and also do not pass any arguments except the first function.

Another issue was a LinkedList. I was not supposed to pass the Head
pointer or add a global variable. The class only had *m_pLink (the
tail pointer). Would it be ok to assign the head pointer to m_pLink
(m_pLink does take current pointer values as it progress throuhgh the
chain, but assigned the top current pointer value)? I did that and the
code works fine.

Thank you
 
N

Noah Roberts

2005 said:
Hi

In C++, are the following considered best practices or not?
- passing aguments to functions (ie functions do not take any arguments
)

Huh? Is it good practice to pass arguments to functions that take no
arguments? Is that what you are asking? No, it is not. It won't even
compile. Normally one passes arguments to functions when the functions
need input, or arguments.
- returning values using return statement

How else would you return values?
Anything else?

Your post isn't making a lot of sense. Maybe you need to think more
clearly about what you are asking.
The reason for this question is that I had an assignment in which I was
asked to modify so that the main will call all the functions from main
itself and also do not pass any arguments except the first function.
Ok.


Another issue was a LinkedList. I was not supposed to pass the Head
pointer or add a global variable. The class only had *m_pLink (the
tail pointer). Would it be ok to assign the head pointer to m_pLink
(m_pLink does take current pointer values as it progress throuhgh the
chain, but assigned the top current pointer value)? I did that and the
code works fine.

I have no idea if that follows the guidelines to your assignment. You
would normally keep track of the head in a linked list. If you track
the tail and link back to the head then really you are just reversing
terminology as conceptually your list is still from head to tail.
 
2

2005

Noah said:
Huh? Is it good practice to pass arguments to functions that take no
arguments? Is that what you are asking? No, it is not. It won't even
compile. Normally one passes arguments to functions when the functions
need input, or arguments.


How else would you return values?


Your post isn't making a lot of sense. Maybe you need to think more
clearly about what you are asking.


I have no idea if that follows the guidelines to your assignment. You
would normally keep track of the head in a linked list. If you track
the tail and link back to the head then really you are just reversing
terminology as conceptually your list is still from head to tail.

Hi

In C++, are the following considered best practices or not?
- passing aguments to functions (ie design functions so that they
better take no arguments)
- returning values using return statement

Anything else?

The reason for this question is that I had an assignment in which I was
asked to modify so that the main will call all the functions from main
itself and also do not pass any arguments except the first function.

Another issue was a LinkedList. I was not supposed to pass the Head
pointer or add a global variable. The class only had *m_pLink (the
tail pointer). Would it be ok to assign the head pointer to m_pLink
(m_pLink does take current pointer values as it progress throuhgh the
chain, but assigned the top current pointer value)? I did that and the
code works fine.

I do Not think that you can get Head if you know the tail?

Thank you
 
W

White Wolf

[SNIP-repeated-post]

When you are asked to clarify please do so. Reposting your original text
verbatim does not help either you, or the people who would like to help.
 
2

2005

White said:
[SNIP-repeated-post]

When you are asked to clarify please do so. Reposting your original text
verbatim does not help either you, or the people who would like to help.

Sorry, the original post - people didn't understand - so I modified it
& posted.
 
M

Mike Wahler

2005 said:
Hi

In C++, are the following considered best practices or not?
- passing aguments to functions (ie design functions so that they
better take no arguments)

A function's purpose will determine whether it's appropriate
to define parameter(s) for it. So 'best practice' is to
use arguments when necessary, and don't when not.
- returning values using return statement

As far as I know, the only way to return a value from
a function is with a return statement.
Anything else?

The reason for this question is that I had an assignment in which I was
asked to modify so that the main will call all the functions from main
itself and also do not pass any arguments except the first function.

This could work (or not) depending upon what the program is supposed to do.
Perhaps this is simply a lesson to show you that there's often more than
one way to do something, and perhaps to decide which is 'better'.
Another issue was a LinkedList. I was not supposed to pass the Head
pointer

Pass it to what?
or add a global variable.

Global objects are rarely necessary and best avoided.
The class only had *m_pLink (the
tail pointer).

Here you say 'm_pLink' represents a tail pointer.
Would it be ok to assign the head pointer to m_pLink

Then 'm_pLink' would not be a tail pointer anymore (except in
the case of an empty list).
(m_pLink does take current pointer values as it progress throuhgh the
chain,

Now you say 'm_pLink' is a 'current pointer'. WHich is it?
but assigned the top current pointer value)?

What is a 'top current pointer'?
I did that and the
code works fine.

What code? Show us.
I do Not think that you can get Head if you know the tail?

Whether you traverse a linked list from beginning to end, or
from end to beginning, you'll need some way of telling when
to stop (typically with a 'NULL' pointer value).

-Mike
 
2

2005

Mike said:
A function's purpose will determine whether it's appropriate
to define parameter(s) for it. So 'best practice' is to
use arguments when necessary, and don't when not.


As far as I know, the only way to return a value from
a function is with a return statement.


This could work (or not) depending upon what the program is supposed to do.
Perhaps this is simply a lesson to show you that there's often more than
one way to do something, and perhaps to decide which is 'better'.


Pass it to what?


Global objects are rarely necessary and best avoided.


Here you say 'm_pLink' represents a tail pointer.


Then 'm_pLink' would not be a tail pointer anymore (except in
the case of an empty list).


Now you say 'm_pLink' is a 'current pointer'. WHich is it?


What is a 'top current pointer'?


What code? Show us.


Whether you traverse a linked list from beginning to end, or
from end to beginning, you'll need some way of telling when
to stop (typically with a 'NULL' pointer value).

If you only know the m_pLink (ie the tail, NULL pointer or the end),
how can you find/evaluate the Head pointer?
 
N

Noah Roberts

2005 said:
If you only know the m_pLink (ie the tail, NULL pointer or the end),
how can you find/evaluate the Head pointer?

You cannot iterate a singly linked list backwards. You also cannot
derive anything about a list if the only information you have about it
is a null pointer. If you consider m_pLink the tail of your list,
which you have decided will be null, which you have decided will
represent the end of your list, you will not be able to acomplish
anything with the m_pLink variable. So, in short, if the only thing
you know about your list is that m_pLink contains a null pointer you
will not be able to find/evaluate the Head pointer.
 
M

Marcus Kwok

Mike Wahler said:
As far as I know, the only way to return a value from
a function is with a return statement.

Well, another way is to return a value through an output parameter. Yet
another is to throw an exception as a return value, though this style is
frowned upon. A third that I can think of is to return a value through
a global variable, also frowned upon.
 
N

Noah Roberts

Marcus said:
Well, another way is to return a value through an output parameter. Yet
another is to throw an exception as a return value, though this style is
frowned upon. A third that I can think of is to return a value through
a global variable, also frowned upon.

None of those qualify as returning a value; they are all side effects.
Throwing an exception is actually completely outside the normal program
flow and doesn't fit in the function concept at all.
 
M

Marcus Kwok

Noah Roberts said:
None of those qualify as returning a value; they are all side effects.

Strictly speaking, yes, but *logically* the effects of the side effects
can be used to return values. For example, a common idiom to "return"
multiple values from a function without introducing things like tuples
is to have them as output parameters:

void foo(int i, int& j, double &d, bool& b);

This prototype could be used for a function that gets passed an int,
does some calculation, then "returns" an int, a double, and a bool.
Throwing an exception is actually completely outside the normal program
flow and doesn't fit in the function concept at all.

In Section 14.5 of _TC++PL_ :

Using exceptions as alternate returns can be an elegant technique for
terminating search functions - especially highly recursive search
functions such as a lookup in a tree. For example:

void fnd(Tree* p, const string& s)
{
if (s == p->str) throw p; // found s
if (p->left) fnd(p->left, s);
if (p->right) fnd(p->right, s);
}

Tree* find(Tree* p, const string& s)
{
try {
fnd(p, s);
}
catch (Tree* q) { // q->str == s
return q;
}
return 0;
}

However, such use of exceptions can easily be overused and lead to
obscure code. Whenever reasonable, one should stick to the
"exception handling is error handling" view.

In the example above, the helper function fnd() returns a pointer
through the exception mechanism.
 
V

Victor Bazarov

Marcus said:
Well, another way is to return a value through an output parameter.

I think that's called "side effect".
Yet another is to throw an exception as a return value, though this
style is frowned upon. A third that I can think of is to return a
value through a global variable, also frowned upon.

Again, a side effect, not "returning a value". Such value cannot
really be used in an expression involving a function call, can it?
Neither can an exception, come to think of it...

V
 
N

Noah Roberts

Marcus said:
In Section 14.5 of _TC++PL_ :

Using exceptions as alternate returns can be an elegant technique for
terminating search functions - especially highly recursive search
functions such as a lookup in a tree. For example:

void fnd(Tree* p, const string& s)
{
if (s == p->str) throw p; // found s
if (p->left) fnd(p->left, s);
if (p->right) fnd(p->right, s);
}

Tree* find(Tree* p, const string& s)
{
try {
fnd(p, s);
}
catch (Tree* q) { // q->str == s
return q;
}
return 0;
}

However, such use of exceptions can easily be overused and lead to
obscure code. Whenever reasonable, one should stick to the
"exception handling is error handling" view.

In the example above, the helper function fnd() returns a pointer
through the exception mechanism.

No, it throws an exception and returns nothing. Throwing an exception
and returning a value are two very different things. Again, exceptions
don't really fit in the function concept at all and are a path of
execution outside of that concept. Abusing them not withstanding.

Also, I would disagree with the Bjarne on this one. Someone else
brought this up a while ago and testing reveiled that on at least one
common architecture the performance penalty for doing it that way was
quite severe when compared to using the actual return mechanism. I
agree that it can obviously be done but is far from elegant or
appropriate.
 
M

Marcus Kwok

Noah Roberts said:
No, it throws an exception and returns nothing. Throwing an exception
and returning a value are two very different things. Again, exceptions
don't really fit in the function concept at all and are a path of
execution outside of that concept. Abusing them not withstanding.

I agree that this is an abuse of the exception mechanism and I would
probably never write code like this. However, I think our disagreement
may be in what our definitions of "returns" are. In this context, I am
using a little more liberal definition, as in "makes a result available
to the calling code". If you use my definition, then the exception
mechanism indeed does make the result available to the calling code,
albeit in a highly unorthodox manner.


#include <iostream>

void foo_ex()
{
throw 42;
}

void bar_ex()
{
int i = 0;
try {
foo_ex();
}
catch (int j) {
i = j;
}
std::cout << "exception: i = " << i << '\n';
}



int foo_ret()
{
return 42;
}

void bar_ret()
{
int i = foo_ret();
std::cout << "return: i = " << i << '\n';
}



int main()
{
bar_ex();
bar_ret();
}

/*
output:
exception: i = 42
return: i = 42
*/


In both cases, 'i' gets the value obtained from foo(). Obviously, the
standard return mechanism is much better. But, with diligence I believe
it should be *possible* to replace all return-statements with
throw-statements, if all invocations of the function are appropiately
wrapped in try/catch blocks so that the stack is never unwound more than
would happen with a regular function, etc. Therefore, throwing an
exception *can* be used as a slow, error-prone, clumsy way to return
values from a function.

Whether this is something that anyone would actually *want* to do is
another matter...
Also, I would disagree with the Bjarne on this one. Someone else
brought this up a while ago and testing reveiled that on at least one
common architecture the performance penalty for doing it that way was
quite severe when compared to using the actual return mechanism.

Yes, I remember that thread.

http://groups.google.com/group/alt.comp.lang.learn.c-c++/browse_frm/thread/1a5e7fef082b5472/

I also see that you weighed in several times in that thread too.
I
agree that it can obviously be done but is far from elegant or
appropriate.

Well, I never said I endorsed this method... just that it is not the
only way to "return" something from a function.
 
N

Noah Roberts

Marcus said:
I agree that this is an abuse of the exception mechanism and I would
probably never write code like this. However, I think our disagreement
may be in what our definitions of "returns" are. In this context, I am
using a little more liberal definition, as in "makes a result available
to the calling code". If you use my definition, then the exception
mechanism indeed does make the result available to the calling code,
albeit in a highly unorthodox manner.

Well, if we call a chicken a duck then the differences between chickens
and ducks obviously becomes quite difficult to talk about.

[snip a bunch of obvious stuff]

Therefore, throwing an
exception *can* be used as a slow, error-prone, clumsy way to return
values from a function.

No, there is only one mechanism for returning values from a function.
 
M

Marcus Kwok

Noah Roberts said:
No, there is only one mechanism for returning values from a function.

Well, my point was that generally exceptions were created as a better
replacement for error return codes. Therefore, by abusing the
mechanism, we can use them to replace regular returns, but with the cost
of worse performance, increased programmer effort, decreased clarity of
code, non-idiomatic constructs, etc.

I don't think either one of us is going to budge on this, so I say we
should just agree to disagree :)
 
N

Noah Roberts

Marcus said:
Well, my point was that generally exceptions were created as a better
replacement for error return codes.

Yes, I see your confusion. Just because something "replaces" something
doesn't mean they are equivelant. One of the great things about using
exceptions for error handling is that error handling is removed from
the standard flow of the program. You now have a totally separate
control path for errors vs. normal program flow.

Basically there are 3 supported methods for information to leave a
function:

1) function side effects: altering reference parameters, pointers, or
global data.
2) exceptions: pulling out of the normal path of execution until an
error handler is hit or exit the program. This actually prematurely
terminates the function being called and enters a different execution
pathway.
3) return a value from the function.

These are all very different things. Only the first and last can be
considered normal things for a function to do.
 
M

Marcus Kwok

Noah Roberts said:
Yes, I see your confusion. Just because something "replaces" something
doesn't mean they are equivelant. One of the great things about using
exceptions for error handling is that error handling is removed from
the standard flow of the program. You now have a totally separate
control path for errors vs. normal program flow.

Right, I never said they were equivalent; exceptions are better for
reporting errors, and 'return' is better for, um, returning values from
a function. Use the right construct for the right job.

You can replace a bicycle with a car. The car is better for some
situations, and a bicycle is better in other situations, but both can do
similar things.
Basically there are 3 supported methods for information to leave a
function:

1) function side effects: altering reference parameters, pointers, or
global data.

OK, no problem.
2) exceptions: pulling out of the normal path of execution until an
error handler is hit or exit the program. This actually prematurely
terminates the function being called and enters a different execution
pathway.

However, if all intermediate operations are nothrow, and the only places
where an exception is thrown is where a normal return statement should
be, and the calling code is wrapped appropriately, then you can write
code *as if* the exception mechanism is your return mechanism.
3) return a value from the function.

Obviously no problem.
These are all very different things. Only the first and last can be
considered normal things for a function to do.

I will agree to this last statement. Under normal circumstances, I
would not use exceptions to propagate values to calling code. But, just
because something is not normally done or shouldn't be done, doesn't
mean it can't be done.
 

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


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top