|
Boost : |
From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-10-24 07:33:22
>From: "Maciej Sobczak" <maciej_at_[hidden]>
> Terje Slettebo wrote:
> >>From: "Maciej Sobczak" <maciej_at_[hidden]>
> >
> >>The mathematics is the same in ancient Rome, in Warsaw and in Tokyo,
> >>even if the numbers *look* differently.
> >
> >>I think that the representation of the class should be separate from the
> >>class. You can achieve this with either separate translator functions
> >>(see the reply from Volodya) or by wrapping integer into some class:
> >
> >>int i = ...;
> >>cout << MyNumber(i);
> >>
> >>MyNumber n;
> >>cin >> n;
> >>int i = n.get();
> >
> > How is MyNumber different from a Roman number class? It seems to me that
it
> > does indeed represent Roman numbers.
>
> No. It is just a way to add type information to the built-in type so
> that the operator overloading can kick in. It is enough to write:
>
> struct MyNumber
> {
> MyNumber(int v) : value_(v) {}
> int value_;
> };
Ok. Well, if you want to make it usable as a value, like int, so you e.g.
can write sum=a+b+c;, then it better have implicit conversion to int. And
then the constructor should be explicit, or you very easily get ambiguity.
> The idea of wrapping built-in type this way comes from my initial
> statement - math does not change across countries (so let's use ints for
> math and other stuff for representation).
How about validation? Should MyNumber accept zero or negative values? Or
should this be left to the output function? If you don't validate in
MyNumber, then you risk getting an error when trying to output it, and the
point the error was introduced (the construction of MyNumber) could be
harder to find. Worse, you could invalidate it along the way, using the
arithmetic operators. How to guard against that?
One way could be to overload operator+(MyNumber,MyNumber), etc. (and have no
implicit conversion to int), but in this case, when you start to overload a
lot of operators, to provide validation, how is that different from a class
doing it? Whether you use a class, or free functions mentioning the class,
it's basically part of the same class (the Interface Principle).
Yes, the operations are the same for ints and Roman numbers, but there are
legal values for ints that are illegal values for Roman numbers. This is a
key point, and it means a Roman number class usable as int (your wrapper)
could be a lot harder to use, than a class, with functions (member or free)
which performs the validation.
If you add functions to perform validation for overloaded math operators,
you basically have a class. So I don't think the idea of a Roman number
class is misdirected at all. If you use free functions to access public data
in the wrapper (as shown above), that also means anybody can put it in an
invalid state. Public get/set functions (unless they validate) amount to the
same.
What if you want to cache the string version of the number? Using just a
thin wrapper, like above, the wrapper can't do that.
As you may see, it may actually make a lot of sense to have a class to
handle this.
Regards,
Terje
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk