|
|
|
|
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Warp wrote:
> In an OO language where constructing an object also initializes it (so that
> it's impossible to have uninitialized objects, which makes sense), it may be
> rational to have more than one constructor for constructing objects in
> different ways. It may also be rational to have a default-constructed object,
> with some sensible default values. (And in some cases being able to
> default-construct objects might be a prerequisite.)
Agreed. This is the main situation where I find it's actually a PITA to
follow the rule. :-) But usually for this sort of thing, your constructor
doesn't take a whole lot of arguments, so making any of them default values
would be reasonable.
I'd expect the best answer would be to have the default constructor (if it
exists) not take any arguments and use a different name for constructors
that take arguments. Calling Point.initialize(0,0) would be just like
calling Point.new().
Of course, using default arguments assumes that there *is* a valid default.
Unless your language supports telling you which arguments didn't get passed
from the caller, you sometimes *have* to use the separate-call pattern.
> Point(); // Default constructor, initializes to (0,0)
> Point(int x, int y); // Initializes to the given values
The same guy also thinks overloaded function names are a bad idea, too,
altho his reasoning on that seems less obvious. (Other than when you
inherit, you wind up with problems if you want to override one version and
not the other, I guess.)
> It becomes cumbersome when you need only a temporary, for example like:
I don't think the original proponent (Meyers) was too worried about
cumbersome as much as he was about correctness and reusability. :-)
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Mike Raiford <"m[raiford]!at"@gmail.com> wrote:
> At least in C# you can't do function pointers.
There are situations where function pointers are actually useful.
Here's one actual example which I have used in the past (simplified here,
of course):
class MyCLP: public CommandLineParser
{
bool debugParamHandler(const std::string&)
{
// do whatever here
}
public:
MyCLP()
{
setOptionHandler("debug", &MyCLP::debugParamHandler,
"The short description of the -debug parameter");
}
};
The idea is that 'CommandLineParser' is a class which parses the command
line parameters (in the project in question it parsed things like the input
and output file names as well as many default parameters supported by all
the programs in the project), and if you want to support a parameter specific
to this program, you specify it with the 'setOptionHandler' function. You
give the function the name of the parameter and a pointer to the function
which CommandLineParser should call when that parameter appears in the
command line.
The internal implementation of CommandLineParser becomes a bit complicated
(for many reasons), but this is by far the best way from the *usage* point
of view. Any other solution would require to always write a lot more code
if you want to add support for a new command-line parameter. This solution
requires the minimum amount of code you have to write in order to do that.
This doesn't mean this could be the only way of implementing this
functionality. It's just the simplest from the usage point of view.
The next best thing would be to have just one generic virtual function
in the base class which gets called when a registered command-line parameter
appears, and then you implement this virtual function. However, you would
have to implement it as a big if... else if... else if... else if... else
block, so it becomes more cumbersome than the way described above.
Another example of where a function pointer can be handy is when wanting
to supply a comparator to a STL algorithm or data container.
For example, suppose that you want to sort an array of objects in a
special way (or simply if the objects don't support the < comparison).
What to do? What you do with the STL is:
std::sort(array.begin(), array.end(), objectComparator);
Now a comparator is "anything that behaves like a function taking two
const references to array elements, and returns a bool". The most obvious
thing which behaves like that is a *function* with that signature. For
example assuming that the element of the array is of type Object, you would
write such a function as:
bool objectComparator(const Object& lhs, const Object& rhs)
{
// return true if lhs < rhs, else false
}
Now if you pass this function as the third parameter for std::sort(),
as above, what you are doing is actually passing a function pointer.
(If you look at the type id of the resulting std::sort() function, the
type of the third parameter will indeed be a function pointer with that
signature.)
It's possible to create an object which behaves like such a function
(a functor object), but it's more writing.
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Darren New escreveu:
> nemesis wrote:
>> More OO, or more assemblyish? I mean, you individually feed the stack
>> and then call a function using those arguments already in the stack. ;)
>
> Well, no, it's not a stack, it's an object. And each call can, for
> example, set error codes or throw exceptions or some such. So if there's
> no letter-sized paper loaded
It's a saved stack, let's say.
> Kind of like the whole command/query separation. A bit more verbose,
> but also more clear and maintainable. (Command/query separation is
> basically that only functions that don't return a value are allowed to
> modify the object. Or, in C++ terms, all non-const methods must be void.)
I don't like the whole OO BS. Despite being submitted to it daily for
the last 20 years or so. Functional programming and scripting too
opened my eyes to a much better model for software programming.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Warp wrote:
> Mike Raiford <"m[raiford]!at"@gmail.com> wrote:
>> At least in C# you can't do function pointers.
>
> There are situations where function pointers are actually useful.
To be clear, C#'s "delegates" are actually a superset of the functionality
of "function pointers". C# wouldn't have any problem with implementing your
examples.
> The next best thing would be to have just one generic virtual function
> in the base class which gets called when a registered command-line parameter
> appears, and then you implement this virtual function. However, you would
> have to implement it as a big if... else if... else if... else if... else
> block, so it becomes more cumbersome than the way described above.
I think better would be the way you wind up having to do it in Java - you
have a class that implements a "parse this" method for each possible
argument to be parsed, and the parser has a map from "-debug" to an instance
of the class that parses the debug parameter. So you have one subclass for
each parser function. Ugly, but not as bad as a giant switch statement.
FWIW, a delegate *is* an object that behaves like a function (your "functor
object"). You write something like
delegate int xyz(float);
int doodoo(float x) { return (int) (x*x); }
xyz = doodoo;
int answer = xyz(27.3);
You can also then say
int foofoo(float y) { return (int) (y * 18.2); }
xyz += foofoo;
Then when you call
xyz(71.3);
it passes 71.3 to doodoo then to foofoo.
Less helpful if you actually need the results, but often delegates are used
as things like callbacks for user interface frobbings or other async events,
so failures tend to be propagated back as exceptions rather than return results.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Invisible escreveu:
> * This is why, if a Haskell function takes any functions as arguments,
> they invariably come *first*, and any data structures come *last*. ;-)
Hmm, this is just a convention, I guess. There's no technical
limitation for a function not appearing last in the argument list.
> Yeah, looks like in about 8 years or so C# or Python or Ruby will have
> stolen everything that is cool about Haskell, and Haskell itself *still*
> won't be popular. :-(
>
> Which is a pitty, really, because few things can match the beauty and
> simplicity of Haskell...
Well, C# can because Microsoft employs the father of Haskell. ;)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Mike Raiford escreveu:
> Darren New wrote:
>> Errr, they are? No. A C++ thing, but not a C thing.
>
> Oh. For some reason I thought they were introduced in C.
huhuhu
C requires much more effort from a programmer aside from assembly... :P
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
nemesis wrote:
> It's a saved stack, let's say.
Uh, no. It's an object. A stack is LIFO, for one thing.
It's a stack only in the sense that if you pass a bunch of parameters to a
function, the function gets a pointer to where they are contiguous in memory
when you invoke the function, not unlike invoking a member method.
> I don't like the whole OO BS. Despite being submitted to it daily for
> the last 20 years or so. Functional programming and scripting too
> opened my eyes to a much better model for software programming.
Yah. It's handy for some things, like where OO is natural. It can be
annoying to try to squeeze functional stuff (like, say, the relational
model) into an OO framework. Most of my code is still procedural, and most
OO code I see (in things like web page servers etc) really doesn't need to
be OO anyway.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Warp wrote:
> Mike Raiford <"m[raiford]!at"@gmail.com> wrote:
>> At least in C# you can't do function pointers.
>
> There are situations where function pointers are actually useful.
> Here's one actual example which I have used in the past (simplified here,
> of course):
>
> class MyCLP: public CommandLineParser
> {
> bool debugParamHandler(const std::string&)
> {
> // do whatever here
> }
>
> public:
> MyCLP()
> {
> setOptionHandler("debug", &MyCLP::debugParamHandler,
> "The short description of the -debug parameter");
> }
> };
>
C# uses delegates, instead. Similar functionality Not as ugly to
declare. Function pointer syntax can get ugly.
>
> std::sort(array.begin(), array.end(), objectComparator);
>
Again, very similar to the predicates used in C#'s extension functions,
which take delegates.
>
> It's possible to create an object which behaves like such a function
> (a functor object), but it's more writing.
>
Which is essentially a delegate :)
I was mainly alluding to the messiness of declaring function pointers.
C# does have a mechanism to do what you've described, though.
--
~Mike
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Darren New wrote:
> xyz += foofoo;
>
> Then when you call
> xyz(71.3);
> it passes 71.3 to doodoo then to foofoo.
>
> Less helpful if you actually need the results, but often delegates are
> used as things like callbacks for user interface frobbings or other
> async events, so failures tend to be propagated back as exceptions
> rather than return results.
What is the difference between a multicast delegate, as shown here, and
an event?
Love the function names, btw..
--
~Mike
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
nemesis wrote:
> Mike Raiford escreveu:
>> Darren New wrote:
>>> Errr, they are? No. A C++ thing, but not a C thing.
>>
>> Oh. For some reason I thought they were introduced in C.
>
> huhuhu
>
> C requires much more effort from a programmer aside from assembly... :P
Considering I started with C++, It's easy for me to blur the lines,
sometimes. I remember declaring structs in C being rather weird.
--
~Mike
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|