TIP: Click on subject to list as thread! ANSI
echo: c_plusplus
to: RENE HERMAN
from: DARIN MCBRIDE
date: 1998-04-28 20:06:00
subject: Questions

 RH> please feel free to pick only question(s) that you feel like answering.
Sounds like my professional exam... "Pick 4 of the following 5 questions..."  
:-)
 RH> If not that, I would also very much welcome an URL for 
 RH> a copy of the draft ANSI C standard, assuming it also 
 RH> includes the standard libary functions. I also read the 
 RH> C_ECHO, and remember a new draft being released? I 
You can get the current standard by ordering a copy of the Annotated ANSI C 
Standard (ISBN 0-07-881952-0) and ignoring the annotations.  Much cheaper 
than ordering straight from ANSI or ISO, I hear.
A new draft is in the works - called C9X.  (So long as it doesn't end up as 
ANSI C '99...)  I don't know where to get a hold of it...
 RH> Should I allow the compiler to allocate enums as single 
 RH> bytes? Or to use unsigned characters by default? It 
 RH> allows me to set these as options, but I believe both 
 RH> could get me into portability trouble? What's standard?
I don't think any of them make portability a problem unless you intend on 
sharing data between your program and another one on the same platform 
(another DOS or Windows app, for example).  If you intend on sharing data 
with other platforms, well, that's another problem entirely.
Another problem arises if you want to share data with a "newer" version of 
your own program.  For example, in V1, you save data in a binary file.  In 
V2, you want to read it - even if it is a V1 file.  Well, you have to make 
sure that the V2 knows how to interpret everything.  Don't worry about this 
until you get there.  (One way to avoid everything is to save your stuff in 
ascii...)
 RH> When overloading operators for a class, when should I 
 RH> implement the functions as member functions, and when 
 RH> as friend functions? My textbook demonstrates both 
 RH> methods, but doesn't say when nor why to use either.
members when possible, friends otherwise... that's my rule.  :-)
For example, if you want to be able to add a foo with an int and end up with 
a foo...
class foo
{
  friend foo operator+(int, const foo&); // int + foo
public:
  foo  operator+(int); // foo + int
  foo& operator+=(int); // foo += int
};
However, even in this case, the friend isn't needed... just have:
foo operator+(int i, const foo& f)
{ return f + i; }
Another way is:
foo operator+(int i, const foo& f)
{ foo f2(f);  return f2 += i; }
And yet another way is:
foo operator+(int i, foo f) // not const nor reference!
{ return f += i; } // we have a local copy of f!
However, this may not work where the operation is not commutative (sp).  That 
is, where a+b != b+a.  Then you would need a friend function.
 RH>   void X::operator=([const] X&);
[Yuk]
 RH>   X& X::operator=([const] X&);
[MUCH better! ]
 RH> returning "*this", as Borland's online help says I 
 RH> should do? Is there a difference?
There is a difference.  For example:
X a, b, c;
// create c
a = b = c; // only if b.operator=(c) returns a reference to either b or c
Note that this is expanded like the comment says:
a.operator=(b.operator=(c));
Now it's just a function call... if X::operator=(const X&) returned void, you 
couldn't do this.  Another one, which I highly don't recommend, is:
(b = c).modifyState();
(Whether b's state or c's state is changed is unknown...)
Thus, IMO, the best way is:
const X& X::operator=(const X&);
Now things like:
(b = c).getState(); // getState is a const function, see below
will work, but modifyState won't.
A const function is not allowed to modify any of the member variables and is 
declared as:
class foo
{
  return_type func(/* parameters or not, as needed */) const;
                                                     //^^^^^ important part
};
return_type foo::func(/* ??? */) const
{                              //^^^^^ has to be here too
  // code
  return rc;
}
So, going back a little bit, we could have:
class foo
{
public:
  foo operator+(int) const; // we return a different foo, not this one
  const foo& operator+(int); // we modify this foo, so it can't be const
};
This const thing is irrespective of parameters - parameters can be const or 
not without making the function const.
 RH> In an exercise which asked to to overload the ++ and -- 
 RH> prefix and postfix operators for a class, I wrote the 
 RH> following test code:
 RH>   cout << "a == " << a.GetValue() << "; ++a == " << ++a << endl
 RH>        << "a == " << a.GetValue() << "; a++ == " << a++ << endl
 RH>        << "a == " << a.GetValue() << "; --a == " << --a << endl
 RH>        << "a == " << a.GetValue() << "; a-- == " << a-- << endl
 RH>        << "a == " << a.GetValue();
Let's expand this a little bit.
cout.operator<<("a == ").operator<<(a.GetValue()).operator<<("; ++a == ")
    .operator<<(++a).operator<<(endl). // etc - you get the idea
So what should happen?  Well, first, cout.operator<<("a == ") should be 
called.  We then take the return from this function (which is an ostream&, 
which just happens to also be cout) and use that to call its operator<<() 
function.  However, we have a major problem.
It's called sequence points.
We have none.
There is no point here that explicitly says "this is where everything needs 
to be synced."  There are only two such places in C/C++: , and ;.
 RH> First I was quite surprised by the really wrong output 
 RH> this produced but after some minutes of hard thought 
 RH> (and cursing buggy compilers), I concluded this really 
 RH> was to be expected as a result of the cdecl (by the 
 RH> way, is that an acronymn?) right-to-left style of 
 RH> argument passing.
Nope - anything and EVERYTHING can be expected by this program.
 RH> "Due apparently to a bug in Borland C++ 4.5, using that 
 RH> compiler did not produce the preceding results. If you 
 RH> experience this problem, repaired in Borland C++ 5, use 
 RH> the following main function, which divides the 
 RH> multipart output statements and ensures that the 
 RH> expressions are evaluated in strict left-to-right 
 RH> fashion: [ 9 couts]"
There's no bug here.  This is due, apparently, to a bug in the author's head 
- this is illegal code and is allowed to produce pretty much whatever result 
that the compiler feels like on the given day.
 RH> Pardon? Bug? Annoying as it is, this behaviour is to be 
 RH> expected of cdecl isn't it? Furthermore, if it is a 
 RH> bug, it doesn't seem fixed...
It's undefined behaviour... and the ultimate undefined behaviour is to format 
your hard drive.  Don't do it.  ;-)  ALWAYS use sequence points when you want 
to modify a variable twice.
a = ++a + 2; // ILLEGAL!  Modifying 'a' twice (operator++ and operator=)!
==========
++a;
a = a + 2; // much better.  (Now change it to a += 2)
==========
a += 3; // even better.  ;-)
 RH> I guess this is a Borland specific question, but is 
 RH> there any way to stop name mangling for class member 
 RH> functions? I know that normally, when implementing 
 RH> functions in an external assembly language module I can 
 RH> declare them as extern "C" to stop name mangling, but 
 RH> the compiler doesn't seem to let me do that with member 
 RH> functions.
Right - because you can have multiple ones with the same name.
class foo
{
  foo(int);
  foo();
  foo(char, char* = NULL);
  baz(int = -1);
  baz(foo*);
  baz(ostream&, char*);
};
What name should it use for each one?
---
---------------
* Origin: Tanktalus' Tower BBS (1:250/102)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.