--------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00123 Date: 04/27/98 From: PETER HAYWOOD Time: 01:57am \/To: MATTHEW CLARK (Read 3 times) Subj: Re: BC++ v5.0 Groovy hepcat Matthew Clark jived with All on 07 Apr 98 16:12:33! BC++ v5.0's a cool scene. Dig it! MC> Hello all, i just bought a copy of borland c++ version 5.0 and I have MC> a question or two. Well, I use a diferent compiler and will be of little help to you, but... MC> If I would make a simply console program that simply outputted some MC> results, as I often need to do in my C++ class, Turbo C++ would MC> compile the program into a console app that would run, terminate, and MC> remain on the screen inactivly until I closed it. With BC5, the app MC> closes as soon as it teminates, so I do not get a change to see my MC> output. MC> A second question, I noticed that it now makes simple console programs MC> into DOS programs instead of windows programs, this is great, but is Both of your questions are related. The reason your program does not stop after execution as it did for those compiled with Turbo, I would expect, is because the new compiler is compiling DOS programs instead of Windows programs. To remedy this, try compiling as Windows programs. Sound simple? Yes, I knew it would. However, I don't know how to do it with your brand of compiler. I assume it does target Windows console applications. You'd know that better than me. The problem is simply that you're not telling the compiler to make a Windows program. You are, whether you know it or not, inadvertantly telling it to make a DOS application instead. RTFM, and learn how to use your compiler. Wolvaen ... The electric chair was invented by a dentist? It figures! --- Blue Wave/RA v2.20 * Origin: The Gate, Melbourne Australia, +61-3-9809-5097 33.6k (3:633/159) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00124 Date: 04/27/98 From: PETER HAYWOOD Time: 01:57am \/To: BLAKE GAFFNEY (Read 3 times) Subj: Re: Local static Groovy hepcat Blake Gaffney jived with All on 10 Apr 98 18:14:22! Local static's a cool scene. Dig it! BG> You know that in good OOP you should avoid global data/functions. I BG> try to do that as often as possible, but sometimes I use static data BG> or functions within a class. BG> What I want to know is, is this as evil as using global BG> data/functions? Think of it this way... Why should you not use too many global variables? It is inconducive of OO principles. That is, global data is not hidden, not part of an object, and as such, is susceptible to errors from unknown or multiple sources. So, does a static variable within a class suffer these problems? No. It is as object oriented as any other variable within a class. Wolvaen ... Well, I'll be a son of a witch! - Bart Simpson --- Blue Wave/RA v2.20 * Origin: The Gate, Melbourne Australia, +61-3-9809-5097 33.6k (3:633/159) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00125 Date: 04/27/98 From: CHRISTIAN FINDLAY Time: 08:57pm \/To: ALL (Read 3 times) Subj: C++ Isn't it just so good! Hi everyone. If you have ever said to yourself "Gee I would like to play Dungeons & Dragons" or "What the hell is Dungeons & Dragons" or "My DM is a F$%^wit" or "What the hell are we gonna do with the DM's body?" then you should try this site site: http://www.geocities.com/SiliconValley/Horizon/4449 Note: This is a new message and you may have tried this site before but this is now correct. Register on this site now! Me and a friend have put together a site to play D&D over the net. All you have to do to register is try out this site. We are play testing it for now so until I we get a Post Office Box you will not have to pay a cent. You don't have to know anything about D&D to play, it will be all explained when you log on. Try getting your friends to play as well, the more ppl that play the more fun the games are and if you get a group together in your Time Zone you can guarantee a regular time slot during the week. If for some reason you can't contact the site try Emailing Kruddler at kruddler34@hotmail.com or dbrede@ibm.net --- FMail/386 1.20+ * Origin: Comms Barrier BBS +61.3.9585.1112, +61.3.9583.6119 (3:632/533) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00126 Date: 04/28/98 From: DARIN MCBRIDE Time: 07:12pm \/To: TIM HUTZLER (Read 3 times) Subj: Re: Default constructor DM>You seem to be misinterpreting what I said. We're talking about DM>how it looks to the new C++ programmer TH> Maybe the discussion *should* be about how it looks to the developers TH> of C++, namely Benjemin what's his name. [grin] There can be two threads on this topic if you wish - one being the advanced thread, and the other being the thread trying to get the newbie to understand the advanced thread. :-) Wow - multithreading! :-) TH> Yes, and it is important to get those concepts in correct TH> *perspective* and accurately defined. There are certain rules no TH> matter what level of programming one is at. And in C++ one of the TH> rules is that there is only *one* _default_ constructor, no TH> arguments, no returns. All other constructors are there to provide TH> the desired functionality. One default constructor per class. class foo { foo(); // foo's default constructor }; class bar { bar(float pressure=101.5); // bar's default constructor }; [If you don't get bar, it's a conversion from kilopascals to... oh nevermind. ] These do the same thing - allow you to create either a foo or a bar without any parameters. But they look different and are thus confusing if you try to combine them. Worse, the latter one is "two" functions in one - taking either 0 or 1 parameter(s). The same code (with different parameters) is called both for bar b1; and bar b2(100.0);. I can understand the difficulty in understanding both of these at the same time, so I prefer the ability to pull the concepts apart as long as we eventually bring them together. [C++ programmers usually come from other languages] TH> True, overloading is an uncommon but nifty feature. But not default TH> arguments - which, BTW, are not the same thing as a default TH> constructor. Default arguments (or parameters, more correctly) can TH> exist in *any* function whether it's a method to a class or not. A In C++, yes. In other languages... no. So we must deal with this concept... :-) TH> default constructor *must* exist in every class. If it is not On the contrary - it does NOT need to exist in ANY class. foo.h===== class foo { public: foo(int i); int m_i; private: foo(); // default constructor? }; foo.cc==== foo::foo(int i) : m_i(i) {} //foo::foo() ... not defined - doesn't exist! ===== Since the default constructor cannot be called, we don't need it. TH> specified (ie. one that takes no arguments), then the compiler will TH> create one - behind the programmers back. Nope. :-) Only if there is no constructor there. If there IS _ANY_ constructor, the default will not be put there for you. For example... I just wrote the following: ====foo.cc==== class foo { public: foo(int i) : m_i(i) {} int m_i; }; void usefoo() { foo f; // line 10 } ============ Compiled it with: ============ [0] d:\tmp\src\g>gcc -v gcc version 2.7.2.1 [0] d:\tmp\src\g>gcc -c foo.cc foo.cc: In function `void usefoo()': foo.cc:10: no matching function for call to `foo::foo ()' foo.cc:6: candidates are: foo::foo(const foo &) foo.cc:4: foo::foo(int) foo.cc:10: in base initialization for class `foo' foo.cc:10: warning: unused variable `class foo f' ============ See the candidates? The copy constructor is built (line 6???), but no default constructor. TH> Default constructors don't take arguments - never. Sure they do. You said that bar has a default constructor ... but it can take a parameter. TH> Try it. Create a class with *one* constructor having one or more TH> parameters. Specify an instance with no arguments. You will find that TH> it both compiles *and* runs. Reason, the default constructor that was TH> ommitted from the code was created by the compiler. I just did. :-) DM>JMNSHO. TH> ??? TH> I'm not up on this acronym. [grin] Just My Not So Humble Opinion. :-) --- * Origin: Tanktalus' Tower BBS (1:250/102) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00127 Date: 04/28/98 From: DARIN MCBRIDE Time: 07:24pm \/To: RENE HERMAN (Read 3 times) Subj: Default constructor TH> Every class MUST have a default constructor. But, if a default TH> constructor (no args) is not specified in your code, the compiler TH> will create one for you. That's why there was no error. RH> But now you're confusing me again. Not only was there RH> no error, but declaring a TTime object as "TTime Time;" RH> really resulted in the compiler calling my constructor RH> with all arguments set to -1, not in calling an RH> automatically generated no argument constructor. Rene, You're obviously right. It will call your constructor. However, the confusing thing here is that your TTime constructor that has all default parameters will become the default constructor as its signature can match "no parameters". RH> Furthermore, why must every class have a default RH> constructor? When I never declare an object of the RH> class without explicitly stating which constructor to RH> use (ie only declare a TTime Time(1, 1, 1980, 0, 0);) RH> there is no use for a default constructor, is there? Right. The only time (no pun intended) you need a default constructor is when you want to use an array of the objects. For example: TTime array[10]; // for whatever reason You have to use the default constructor for this. Another example is the Standard Template Library - but don't worry about this quite yet. :-) RH> Also, with simple classes that don't declare any RH> virtual functions, there's really nothing to construct. Objects don't need to have virtual functions to need to construct. For example, think about a fstream - a file stream. You can have the constructor open the file for you - so it needs to construct. However, if you have a virtual function, the constructor will be added for this in all cases. RH> ; RH> ; { RH> ; TClass Class; [No assembly output] Because you have "optimized" this away. Try having TClass have a member variable that is another class! For example, having a fstream as a member! class TClass { fstream f; // ... }; The construction will no longer be trivial, and thus you will have a function call here. --- * Origin: Tanktalus' Tower BBS (1:250/102) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00128 Date: 04/28/98 From: DARIN MCBRIDE Time: 07:31pm \/To: RENE HERMAN (Read 3 times) Subj: Default constructor DM> Your TTime objects encapsulates a real object (in this case, an DM> abstract object that humans believe we understand): time. RH> I see what you mean, and regret having to disagree with RH> you. My TTime objects really didn't do anything I disagree with your disagreement. :-) RH> remotely resembling encapsulating the real world RH> concept of time, or even my notion of such a concept. RH> What's the substance of time (its data members) and RH> what influences it, that is, which methods should I RH> provide? If I knew, I would have won a Nobel prize. :-) You provide the methods that you need. It is still an encapsulation, even if it isn't "fully complete" yet. Ideally, yes, your time class would be a complete encapsulation, but, in practicality, it just needs to do what is needed - anything else is superfluous. While programmers are good at "superfluous", at some point we need to get on with the program. :-) RH> I hope I'm not over-interpreting your comments, but in my humble opinion RH> object orientation shouldn't be made out to be more RH> than a way of organizing computer code with advantages RH> such as clarity and modularity, and disadvantages such The clarity advantage is because we can "relate" with the code. We know what time is - if we need to do something to/with a TTime object, we will know, almost intuitively, whether that something should be in the TTime class or external. If we need to increment our time by 1 day, we know that is for the TTime class. RH> as size and speed of the resulting code. Although it at RH> times might provide for a useful abstraction, I feel RH> that most real world objects, let alone concepts such RH> as time, are far too complex to be encapsulated by, or RH> even described by, a set amount of data and functions RH> to operate on that data. On the contrary - they are only too complex if you insist on a complete abstraction. We don't need to be complete, only "good enough". If, at some future point, we need more completeness, we have a single place to update, and everyone gets the functionality for free. I like to think of it as modularity on speed. :-) DM> A class is merely a description of what an object is and what DM> messages can be sent to it. RH> I just browsed the chapter on Windows programming using RH> OWL, but I guess here you mean "which methods it has RH> for operating on an object of the class" when you say RH> "what messages can be send to it"? :-) In OO terminology, you only pass messages to an object. C++ does this via member functions. (Objective C uses something closer to real messages.) This terminology makes it even simpler to see the correspondance between message-based GUIs, such as Windows or OS/2, and C++ windowing libraries. DM> Any time I see "m_" in front of a variable, I know I can find its DM> definition in the class - it is local to the class, but still global DM> in that it can be modified by multiple functions. RH> Will have to consider this. I don't really like the RH> "this->" method myself, but naming a constructors RH> arguments the same as the class's data members does RH> lend some clarity to the code, as far as I'm concerned. RH> By the way, what does the "m" signify? I'm not sure I m_, g_, etc., are extentions to Hungarian notation. These are for Member variables, Global variables, or whatever. The letter before the underscore is typically a scope indicator. Not that everyone likes Hungarian, though... again, a style thing. RH> understand your comment about the "multiple" functions. Multiple functions - member variables can be acted upon by all member and friend functions (assuming they're private - if public, they're the same as global...). Global variables can be acted upon by ... not "multiple" but "all" functions. Locals can obviously only be acted upon by that function. RH> Is there any other type? All class data members can be RH> modified by all (non const) member functions, can they RH> not? Right - I was only making a distinction between local, member, and global variables as for one, some, and all, respectively. DM> TExample(char* s) : s(strdup(s)) DM> {} RH> I just might like this approach... :-) Pretty much standard. And very preferred. DM> I also have a "cchar" class that handles the strdup/delete paradigm DM> for you - it puts an array on the heap but it looks like any other DM> array on the stack - you don't have to delete it. :-) RH> I am somewhat of a minimalist, I really prefer doing RH> things such as that explicitly. Keeps me in touch with RH> what's going on. :-) I go the other direction - I want the compiler to do my work so I can concentrate on NEW things. :-) RH> you aren't even sure yours will? For instance, I was RH> wondering if it were safe to pass a NULL pointer to RH> strdup, which would allow me to write something like [...] RH> without having to check for s being NULL first. Neither RH> Borland's online help nor Tom Swan's function reference RH> said one way or the other, so I had to dig into the RTL RH> source to find out it *wasn't* safe, at least not on my RH> compiler. I'm assuming the standard would have RH> explicitly told me so. It would have implicitly told you that strdup is non-standard. ;-) You're on your own automatically now. :-> --- * Origin: Tanktalus' Tower BBS (1:250/102) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00129 Date: 04/28/98 From: DARIN MCBRIDE Time: 08:06pm \/To: RENE HERMAN (Read 3 times) Subj: 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) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00130 Date: 04/29/98 From: KURT KUZBA Time: 11:48pm \/To: RENE HERMAN (Read 3 times) Subj: Default constructor RH> For instance, I was wondering if it were safe to pass a RH> NULL pointer to strdup, which would allow me to write RH> something like RH> TExample::TExample(const char *s) RH> { RH> this->s = strdup(s); RH> } RH> without having to check for s being NULL first. RH> Neither Borland's online help nor Tom Swan's function RH> reference said one way or the other, so I had to dig RH> into the RTL source to find out it *wasn't* safe, at RH> least not on my compiler. RH> I'm assuming the standard would have explicitly told me so. I know this will sound silly, but why would you want to use strdup() in C++?? The string class IS safe, and easier to use. Where TExample.s is defined as a class of type String: TExample::TExample(const char *s) { this->s = s; } It doesn't get any more simple than this. I know it's beside the point, which is documentation for the RTL functions, but the Class Libraries often provide safe, and often superior, support for many data functions. > ] So far, nobody has ever wanted to ride the Unicorn twice.... --- * Origin: *YOPS ]I[* 8.4 GIG * RA/FD/FE * Milwaukee, WI (1:154/750) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00131 Date: 04/29/98 From: ADAM MAJER Time: 04:26pm \/To: CARLTON WALTERS (Read 3 times) Subj: can you find an error in CW>Turbo C Project File No. Nothing out of the ordinary :) * SLMR 2.1a *On a clear disk you can seek forever --- FMail 0.92 * Origin: The Programmer's Oasis on FIDONET! (1:348/203) --------------- FIDO MESSAGE AREA==> TOPIC: 203 C++ Ref: F5G00132 Date: 04/30/98 From: DARRELL HNIZDOR Time: 09:14am \/To: TIM HUTZLER (Read 3 times) Subj: Re: Modem I will try again. you should have your email before you see this. If you don't reply and I will try again. --- Platinum Xpress/Win/Wildcat5! v2.0 * Origin: Friendship Corner Albany, TX 915-762-2745 (1:392/25)