home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-06-01 | 43.1 KB | 897 lines | [TEXT/EDIT] |
- Newsgroups: comp.lang.c++
- Path: bloom-beacon.mit.edu!noc.near.net!usenet.elf.com!rpi!clarkson!cheetah.ece.clarkson.edu!cline
- From: cline@cheetah.ece.clarkson.edu (Marshall Cline)
- Subject: C++ FAQ: posting #1/4
- Message-ID: <1994May9.131212.28989@news.clarkson.edu>
- Followup-To: comp.lang.c++
- Summary: Please read this before posting to comp.lang.c++
- Sender: cline@sun.soe.clarkson.edu
- Nntp-Posting-Host: cheetah.ece.clarkson.edu
- Reply-To: cline@parashift.com (Marshall Cline)
- Organization: Paradigm Shift, Inc (training/OOD/C++/libraries)
- Date: Mon, 9 May 1994 13:12:12 GMT
- Expires: Thu, 9 Jun 1994 13:12:12 GMT
- Lines: 881
-
- comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
- Copyright (C) 1991-93 Marshall P. Cline, Ph.D.
- Posting 1 of 4.
-
- ((((( THERE HAVE NOT BEEN ANY CHANGES SINCE LAST MONTH )))))
-
- ==============================================================================
- SECTION 1: Introduction and table of contents
- ==============================================================================
-
- Document: Frequently-Asked-Questions for comp.lang.c++
- Revision: Sep 13, 1993
-
- Author: Marshall P. Cline, Ph.D.
- Paradigm Shift, Inc.
- One Park St. / Norwood, NY 13668
- voice: 315-353-6100
- fax: 315-353-6110
- email: cline@parashift.com
-
- Copyright: Copyright (C), 1991-93 Marshall P. Cline, Ph.D.
- Permission to copy all or part of this work is granted,
- provided that the copies are not made or distributed
- for resale (except nominal copying fee may be charged),
- and provided that the NO WARRANTY, author-contact, and
- copyright notice are retained verbatim & are displayed
- conspicuously. If anyone needs other permissions that
- aren't covered by the above, please contact the author.
-
- NO WARRANTY: THIS WORK IS PROVIDED ON AN "AS IS" BASIS. THE AUTHOR
- PROVIDES NO WARRANTY WHATSOEVER, EITHER EXPRESS OR
- IMPLIED, REGARDING THE WORK, INCLUDING WARRANTIES WITH
- RESPECT TO ITS MERCHANTABILITY OR FITNESS FOR ANY
- PARTICULAR PURPOSE.
-
- Availability: This is available via anonymous ftp
- from: sun.soe.clarkson.edu [128.153.12.3]
- in the file: pub/C++/FAQ
-
- Without FTP: You can also get it by sending electronic mail:
- | To: archive-server@sun.soe.clarkson.edu
- | Subject: send C++/FAQ
- This will help those who don't have ftp.
- (note: I hear the mail server is down; if you have problems,
- send details and I'll look into it).
-
- See also: comp.lang.c's FAQ appears at the beginning of every
- month in that newsgroup, and is maintained by
- Steve Summit (scs@adm.mit.edu).
-
- ==============================================================================
- SUBSECTION 1A: Table of Contents
- ==============================================================================
-
- ========== POSTING #1 ==========
-
- SECTION 1: Introduction and table of contents
- SUBSECTION 1A: Table of Contents
- SUBSECTION 1B: Nomenclature and Common Abbreviations
-
- SECTION 2: Environmental/managerial issues
- Q1: What is C++? What is OOP?
- Q2: What are some advantages of C++?
- Q3: Who uses C++?
- Q4: Are there any C++ standardization efforts underway?
- Q5: Where can I ftp a copy of the latest ANSI-C++ draft standard?
- Q6: Is C++ backward compatible with ANSI-C?
- Q7: How long does it take to learn C++?
-
- SECTION 3: Basics of the paradigm
- Q8: What is a class?
- Q9: What is an object?
- Q10: What is a reference?
- Q11: What happens if you assign to a reference?
- Q12: How can you reseat a reference to make it refer to a different object?
- Q13: When should I use references, and when should I use pointers?
- Q14: What are inline fns? What are their advantages? How are they declared?
-
- SECTION 4: Constructors and destructors
- Q15: What is a constructor? Why would I ever use one?
- Q16: How can I make a constructor call another constructor as a primitive?
- Q17: What are destructors really for? Why would I ever use them?
-
- SECTION 5: Operator overloading
- Q18: What is operator overloading?
- Q19: What operators can/cannot be overloaded?
- Q20: Can I create a `**' operator for `to-the-power-of' operations?
-
- SECTION 6: Friends
- Q21: What is a `friend'?
- Q22: Do `friends' violate encapsulation?
- Q23: What are some advantages/disadvantages of using friends?
- Q24: What does it mean that `friendship is neither inherited nor transitive'?
- Q25: When would I use a member function as opposed to a friend function?
-
- SECTION 7: Input/output via <iostream.h> and <stdio.h>
- Q26: How can I provide printing for a `class X'?
- Q27: Why should I use <iostream.h> instead of the traditional <stdio.h>?
- Q28: Printf/scanf weren't broken; why `fix' them with ugly shift operators?
-
- ========== POSTING #2 ==========
-
- SECTION 8: Freestore management
- Q29: Does `delete ptr' delete the ptr or the pointed-to-data?
- Q30: Can I free() ptrs alloc'd with `new' or `delete' ptrs alloc'd w/ malloc()?
- Q31: Why should I use `new' instead of trustworthy old malloc()?
- Q32: Why doesn't C++ have a `realloc()' along with `new' and `delete'?
- Q33: How do I allocate / unallocate an array of things?
- Q34: What if I forget the `[]' when `delete'ing array allocated via `new X[n]'?
-
- SECTION 9: Debugging and error handling
- Q35: How can I handle a constructor that fails?
- Q36: How can I compile-out my debugging print statements?
-
- SECTION 10: Const correctness
- Q37: What is `const correctness'?
- Q38: Is `const correctness' a good goal?
- Q39: Is `const correctness' tedious?
- Q40: Should I try to get things const correct `sooner' or `later'?
- Q41: What is a `const member function'?
- Q42: What is an `inspector'? What is a `mutator'?
- Q43: What is `casting away const in an inspector' and why is it legal?
- Q44: But doesn't `cast away const' mean lost optimization opportunities?
-
- SECTION 11: Inheritance
- Q45: What is inheritance?
- Q46: Ok, ok, but what is inheritance?
- Q47: How do you express inheritance in C++?
- Q48: What is `incremental programming'?
- Q49: Should I pointer-cast from a derived class to its base class?
- Q50: Derived* --> Base* works ok; why doesn't Derived** --> Base** work?
- Q51: Does array-of-Derived is-NOT-a-kind-of array-of-Base mean arrays are bad?
- SUBSECTION 11A: Inheritance -- virtual functions
- Q52: What is a `virtual member function'?
- Q53: What is dynamic dispatch? Static dispatch?
- Q54: Can I override a non-virtual fn?
- Q55: Why do I get the warning "Derived::foo(int) hides Base::foo(double)"?
- SUBSECTION 11B: Inheritance -- conformance
- Q56: Can I `revoke' or `hide' public member fns inherited from my base class?
- Q57: Is a `Circle' a kind-of an `Ellipse'?
- Q58: Are there other options to the `Circle is/isnot kind-of Ellipse' dilemma?
- SUBSECTION 11C: Inheritance -- access rules
- Q59: Why can't I access `private' things in a base class from a derived class?
- Q60: What's the difference between `public:', `private:', and `protected:'?
- Q61: How can I protect subclasses from breaking when I change internal parts?
- SUBSECTION 11D: Inheritance -- constructors and destructors
- Q62: Why does base ctor get *base*'s virtual fn instead of the derived version?
- Q63: Does a derived class dtor need to explicitly call the base destructor?
- SUBSECTION 11E: Inheritance -- private and protected inheritance
- Q64: How do you express `private inheritance'?
- Q65: How are `private derivation' and `containment' similar? dissimilar?
- Q66: Should I pointer-cast from a `privately' derived class to its base class?
- Q67: Should I pointer-cast from a `protected' derived class to its base class?
- Q68: What are the access rules with `private' and `protected' inheritance?
- Q69: Do most C++ programmers use containment or private inheritance?
-
- SECTION 12: Abstraction
- Q70: What's the big deal of separating interface from implementation?
- Q71: How do I separate interface from implementation in C++ (like Modula-2)?
- Q72: What is an ABC (`abstract base class')?
- Q73: What is a `pure virtual' member function?
- Q74: How can I provide printing for an entire hierarchy rooted at `class X'?
- Q75: What is a `virtual destructor'?
- Q76: What is a `virtual constructor'?
-
- ========== POSTING #3 ==========
-
- SECTION 13: Style guidelines
- Q77: What are some good C++ coding standards?
- Q78: Are coding standards necessary? sufficient?
- Q79: Should our organization determine coding standards from our C experience?
- Q80: Should I declare locals in the middle of a fn or at the top?
- Q81: What source-file-name convention is best? `foo.C'? `foo.cc'? `foo.cpp'?
- Q82: What header-file-name convention is best? `foo.H'? `foo.hh'? `foo.hpp'?
- Q83: Are there any lint-like guidelines for C++?
-
- SECTION 14: C++/Smalltalk differences and keys to learning C++
- Q84: Why does C++'s FAQ have a section on Smalltalk? Is this Smalltalk-bashing?
- Q85: What's the difference between C++ and Smalltalk?
- Q86: What is `static typing', and how is it similar/dissimilar to Smalltalk?
- Q87: Which is a better fit for C++: `static typing' or `dynamic typing'?
- Q88: How can you tell if you have a dynamically typed C++ class library?
- Q89: Will `standard C++' include any dynamic typing primitives?
- Q90: How do you use inheritance in C++, and is that different from Smalltalk?
- Q91: What are the practical consequences of diffs in Smalltalk/C++ inheritance?
- Q92: Do you need to learn a `pure' OOPL before you learn C++?
- Q93: What is the NIHCL? Where can I get it?
-
- SECTION 15: Reference and value semantics
- Q94: What is value and/or reference semantics, and which is best in C++?
- Q95: What is `virtual data', and how-can / why-would I use it in C++?
- Q96: What's the difference between virtual data and dynamic data?
- Q97: Should class subobjects be ptrs to freestore allocated objs, or contained?
- Q98: What are relative costs of the 3 performance hits of allocated subobjects?
- Q99: What is an `inline virtual member fn'? Are they ever actually `inlined'?
- Q100: Sounds like I should never use reference semantics, right?
- Q101: Does the poor performance of ref semantics mean I should pass-by-value?
-
- ========== POSTING #4 ==========
-
- SECTION 16: Linkage-to/relationship-with C
- Q102: How can I call a C function `f()' from C++ code?
- Q103: How can I create a C++ function `f()' that is callable by my C code?
- Q104: Why's the linker giving errors for C/C++ fns being called from C++/C fns?
- Q105: How can I pass an object of a C++ class to/from a C function?
- Q106: Can my C function access data in an object of a C++ class?
- Q107: Why do I feel like I'm `further from the machine' in C++ as opposed to C?
-
- SECTION 17: Pointers to member functions
- Q108: What is the type of `ptr-to-member-fn'? Is it diffn't from `ptr-to-fn'?
- Q109: How can I ensure `X's objects are only created with new, not on the stack?
- Q110: How do I pass a ptr to member fn to a signal handler,X event callback,etc?
- Q111: Why am I having trouble taking the address of a C++ function?
- Q112: How do I declare an array of pointers to member functions?
-
- SECTION 18: Container classes and templates
- Q113: How can I insert/access/change elements from a linked list/hashtable/etc?
- Q114: What's the idea behind `templates'?
- Q115: What's the syntax / semantics for a `function template'?
- Q116: What's the syntax / semantics for a `class template'?
- Q117: What is a `parameterized type'?
- Q118: What is `genericity'?
- Q119: How can I fake templates if I don't have a compiler that supports them?
-
- SECTION 19: Nuances of particular implementations
- Q120: Why don't variable arg lists work for C++ on a Sun SPARCstation?
- Q121: GNU C++ (g++) produces big executables for tiny programs; Why?
- Q122: Is there a yacc-able C++ grammar?
- Q123: What is C++ 1.2? 2.0? 2.1? 3.0?
- Q124: How does the lang accepted by cfront 3.0 differ from that accepted by 2.1?
- Q125: Why are exceptions going to be implemented after templates? Why not both?
- Q126: What was C++ 1.xx, and how is it different from the current C++ language?
-
- SECTION 20: Miscellaneous technical and environmental issues
- SUBSECTION 20A: Miscellaneous technical issues:
- Q127: Why are classes with static data members getting linker errors?
- Q128: What's the difference between the keywords struct and class?
- Q129: Why can't I overload a function by its return type?
- Q130: What is `persistence'? What is a `persistent object'?
- SUBSECTION 20B: Miscellaneous environmental issues:
- Q131: Is there a TeX or LaTeX macro that fixes the spacing on `C++'?
- Q132: Where can I access C++2LaTeX, a LaTeX pretty printer for C++ source?
- Q133: Where can I access `tgrind', a pretty printer for C++/C/etc source?
- Q134: Is there a C++-mode for GNU emacs? If so, where can I get it?
- Q135: What is `InterViews'?
- Q136: Where can I get OS-specific questions answered (ex:BC++,DOS,Windows,etc)?
- Q137: Why does my DOS C++ program says `Sorry: floating point code not linked'?
-
- ==============================================================================
- SUBSECTION 1B: Nomenclature and Common Abbreviations
- ==============================================================================
-
- Here are a few of the abbreviations/etc used in this article:
-
- term meaning
- ==== ===========
- ctor constructor
- copy-ctor copy constructor (also `X(const X&)', pronounced `X-X-ref')
- dtor destructor
- fn function
- fns functions
- ptr pointer, a C/C++ construct declared by: int * p;
- ref reference, a C++ construct declared by: int & r;
- OO object-oriented
- OOP object-oriented programming
- OOPL object-oriented programming language
- method an alternate term for `member function'
-
- ==============================================================================
- SECTION 2: Environmental/managerial issues
- ==============================================================================
-
- Q1: What is C++? What is OOP?
-
- C++ can be used simply as `a better C', but that is not its real advantage.
- C++ is an object-oriented programming language (OOPL). OOPLs appear to be the
- current `top shelf' in the development of programming languages that can manage
- the complexity of large software systems.
-
- Some OOP hype: software engineering is `failing' to provide the current users
- demands for large, complex software systems. But this `failure' is actually
- due to SE's *successes*. In other words, structured programming was developed
- to allow software engineers to design/build HUGE software systems (that's a
- success). When users saw how successful these systems were, they said, `More
- --- give me MOOORRRREEEE'. They wanted more power, more features, more
- flexibility. 100K line systems are almost commonplace nowadays, and they still
- want more. Structured programming techniques, some say, begin to break down
- around 100K lines (the complexity gives the design team too many headaches, and
- fixing one problem breaks 5 more, etc). So pragmatics demands a better
- paradigm than structured programming. Hence OO-design.
-
- ==============================================================================
-
- Q2: What are some advantages of C++?
-
- GROWTH OF C++: C++ is by far the most popular OOPL. Knowing C++ is a good
- resume-stuffer. But don't just use it as a better C, or you won't be using all
- its power. Like any quality tool, C++ must be used the way it was designed to
- be used. The number of C++ users is doubling every 7.5 to 9 months. This
- exponential growth can't continue forever(!), but it is becoming a significant
- chunk of the programming market (it's already the dominant OOPL).
-
- ENCAPSULATION: For those of you who aren't on a team constructing software
- mega-systems, what does C++ buy you? Here's a trivial example. Suppose you
- want a `Foible' data type. One style of doing this in `C' is to create a
- `Foible.h' file that holds the `public interface', then stick all the
- implementation into a `Foible.c' file. Encapsulation (hiding the details) can
- be achieved by making all data elements in `Foible.c' be `static'. But that
- means you only get one `Foible' in the entire system, which is ok if `Foible'
- is a Screen or perhaps a HardDisk, but is lousy if Foible is a complex number
- or a line on the screen, etc. Read on to see how it's done in `C' vs `C++'.
-
- MULTIPLE INSTANCES: The `C' solution to the above `multiple instances' problem
- is to wrap all the data members in a struct (like a Pascal `record'), then pass
- these structs around as if they were the `ComplexNumber' or whatever. But this
- loses encapsulation. Other techniques can be devised which allow both multiple
- instances and encapsulation, however these lose on other accounts (ex:
- typedef'ing `Foible' to be `void*' loses type safety, and wrapping a `void*' in
- the Foible struct loses an extra layer of indirection). So the `module'
- technique loses multiple instantiations, but the `struct' technique loses
- encapsulation. C++ allows you to combine the best of both worlds - you can
- have what amount to structs whose data is hidden.
-
- INLINE FUNCTION CALLS: The `encapsulated C' solution above requires a function
- call to access even trivial fields of the data type (if you allowed direct
- access to the struct's fields, the underlying data structure would become
- virtually impossible to change since too many pieces of code would *rely* on it
- being the `old' way). Function call overhead is small, but can add up. C++
- provides a solution by allowing function calls to be expanded `inline', so you
- have: the (1) safety of encapsulation, (2) convenience of multiple instances,
- (3) speed of direct access. Furthermore the parameter types of these inline
- functions are checked by the compiler, an improvement over C's #define macros.
-
- OVERLOADING OPERATORS: For the `ComplexNumber' example, you want to be able to
- use it in an expression `just as if' it was a builtin type like int or float.
- C++ allows you to overload operators, so you can tell the compiler what it
- means for two complex numbers to be added, subtracted, multiplied, etc. This
- gives you: z0 = (z1 + z2) * z3 / z4; Furthermore you might want string1+string2
- to mean string concatenation, etc. One of the goals of C++ is to make user
- defined types `look like' builtin types. You can even have `smart pointers',
- which means a pointer `p' could actually be a user defined data type that
- `points' to a disk record (for example). `Dereferencing' such a pointer (ex:
- i=*p;) means ``seek to the location on disk where p `points' and return its
- value''. Also statements like p->field=27; can store things on disk, etc. If
- later on you find you can fit the entire pointed-to data structure in memory,
- you just change the user-defined pseudo-pointer type and recompile. All the
- code that used these `pseudo pointers' doesn't need to be changed at all.
-
- INHERITANCE: We still have just scratched the surface. In fact, we haven't
- even gotten to the `object-oriented' part yet! Suppose you have a Stack data
- type with operations push, pop, etc. Suppose you want an InvertableStack,
- which is `just like' Stack except it also has an `invert' operation. In `C'
- style, you'd have to either (1) modify the existing Stack module (trouble if
- `Stack' is being used by others), or (2) copy Stack into another file and text
- edit that file (results in lots of code duplication, another chance to break
- something tricky in the Stack part of InvertableStack, and especially twice as
- much code to maintain). C++ provides a much cleaner solution: inheritance.
- You say `InvertableStack inherits everything from Stack, and InvertableStack
- adds the invert operation'. Done. Stack itself remains `closed' (untouched,
- unmodified), and InvertableStack doesn't duplicate the code for push/pop/etc.
-
- POLYMORPHISM: The real power of OOP isn't just inheritance, but is the ability
- to pass an InvertableStack around as if it actually were a Stack. This is
- `safe' since (in C++ at least) the is-a relation follows public inheritance
- (ie: a InvertableStack is-a Stack that can also invert itself). Polymorphism
- is easiest to understand from an example, so here's a `classic': a graphical
- draw package might deal with Circles, Squares, Rectangles, general Polygons,
- and Lines. All of these are Shapes. Most of the draw package's functions need
- a `Shape' parameter (as opposed to some particular kind of shape like Square).
- Ex: if a Shape is picked by a mouse, the Shape might get dragged across the
- screen and placed into a new location. Polymorphism allows the code to work
- correctly even if the compiler only knows that the parameter is a `Shape'
- without knowing the exact kind of Shape it is. Furthermore suppose the
- `pick_and_drag(Shape*) function just mentioned was compiled on Tuesday, and on
- Wednesday you decide to add the Hexagon shape. Strange as it sounds,
- pick_and_drag() will still work with Hexagons, even though the Hexagon didn't
- even exist when pick_and_drag() was compiled!! (it's not really `amazing' once
- you understand how the C++ compiler does it -- but it's still very convenient!)
-
- ==============================================================================
-
- Q3: Who uses C++?
- A: Lots and lots of companies and government sites. Lots.
- Statistically, 20 to 30 people will consider themselves to be new C++
- programmers before you finish reading the responses to these FAQs.
-
- ==============================================================================
-
- Q4: Are there any C++ standardization efforts underway?
- A: Yes; ANSI (American) and ISO (International) groups are working closely with
- each other.
-
- `X3J16' is the name of the ANSI-C++ committee.
-
- `WG21' is the name of ISO's C++ standards group.
-
- The committees are using the `ARM' as a base document:
- `Annotated C++ Reference Manual', Ellis and Stroustrup, Addison/Wesley.
- ISBN 0-201-51459-1
-
- The major players in the ANSI/ISO C++ standards process includes just about
- everyone:
-
- AT&T, IBM, DEC, HP, Sun, MS, Borland, Zortech, Apple, OSF, <add your favorite
- here>, ... and a lot of users and smaller companies. About 70 people attend
- each ANSI C++ meeting. People come from USA, UK, Japan, Germany, Sweden,
- Denmark, France, ... (all have `local' committees sending official
- representatives and conducting `local' meetings).
-
- Optimistically the standard might be finished by 1995-6 time frame (this is
- fast for a proper standards process).
-
- ==============================================================================
-
- Q5: Where can I ftp a copy of the latest ANSI-C++ draft standard?
- A: You can't. ANSI standards and/or drafts are NOT available in machine
- readable form.
-
- >>>>UPDATED 9/93
- You can get a paper copy by sending a request to:
- Standards Secretariat
- CBEMA/X3
- 1250 I Street NW
- Suite 200
- Washington, DC 20005
-
- Ask for the latest version of `Working Paper for Draft Proposed American
- National Standard for Information Systems -- Programming Language C++'.
- The last known phone number: 202-626-5738. The last known price is $25.
-
- ==============================================================================
-
- Q6: Is C++ backward compatible with ANSI-C?
- A: Almost. C++ is as close as possible to compatible with ANSI-C but no closer.
- In practice, the major difference is that C++ requires prototypes, and that
- `f()' declares a function that takes no parameters, while ANSI-C rules state
- that `f()' declares a function that takes any number of parameters of any type.
- There are some very subtle differences as well, like the sizeof a char literal
- being equal to the sizeof a char (in ANSI-C, sizeof('x') is the sizeof an int).
- Structure `tags' are in the same namespace as other names in C++, but C++ has
- some warts to take care of backward compatibility here.
-
- ==============================================================================
-
- Q7: How long does it take to learn C++?
- A: I and others teach standard industry `short courses' (for those not familiar
- with these, you pack a university semester course into one 40hr work-week), and
- have found them successful. However mastery takes experience, and there's no
- substitute for time. Laboratory time is essential for any OOP course, since it
- allows concepts to `gel'.
-
- Generally people start out wondering why the company has devoted a full 5 days
- to something as trivial as another programming language. Then about half way
- through, they realize they're not being taught just a new syntax, but an
- entirely different way of thinking and programming and designing and . . . .
- Then they begin to feel dumb, since they can't quite grasp what is being said.
- Then they get mad and wonder why the course isn't taught in two or three weeks
- instead. Finally about Wednesday afternoon the lights go `clink', and their
- faces brighten, and they `get it'. By Friday, they've had numerous laboratory
- `experiments' and they've seen both sides of reusable components (both how to
- code *from* reuse, and how to code *for* reuse). It's different in every time
- I teach, but the `reuse' aspect is rewarding, since it has a large potential to
- improve software production's overall economics.
-
- It takes 9 months to `master' C++/OOP. Less if there is already a body of
- experts and code that programmers have regular access to, more if there isn't a
- `good' general purpose C++ class library available.
-
- ==============================================================================
- SECTION 3: Basics of the paradigm
- ==============================================================================
-
- Q8: What is a class?
- A: A class defines a data type, much like a struct would be in C. In a CompSci
- sense, a type consists of two things: a set of values *and* a set of operations
- which operate on those values. Thus `int' all by itself isn't a true `type'
- until you add operations like `add two ints' or `int*int', etc. In exactly the
- same way, a `class' provides a set of (usually `public') operations, and a set
- of (usually non-public) data bits representing the abstract values that
- instances of the type can have. From a C language perspective, a `class' is a
- `struct' whose members default to `private'.
-
- ==============================================================================
-
- Q9: What is an object?
- A: An object is a region of storage with associated semantics. After the
- declaration `int i;', we say that `i is an object of type int'. In C++/OOP,
- `object' is usually used to mean `an instance of a class'. Thus a class
- defines the behavior of possibly many objects (instances).
-
- ==============================================================================
-
- Q10: What is a reference?
- A: A reference is an alias (an alternate name) for an object. It is frequently
- used for pass-by-reference; ex:
-
- void swap(int& i, int& j)
- {
- int tmp = i;
- i = j;
- j = tmp;
- }
-
- main()
- {
- int x, y;
- //...
- swap(x,y);
- }
-
- Here `i' and `j' are aliases for main's `x' and `y' respectively. The effect
- is as if you used the C style pass-by-pointer, but the `&' is moved from the
- caller into the callee. Pascal enthusiasts will recognize this as a VAR param.
-
- ==============================================================================
-
- Q11: What happens if you assign to a reference?
- A: Assigning to a reference changes the referred-to value, thus a ref is an
- `Lvalue' (something that can appear on the `L'eft-hand-side of an assignment
- statement) for the referred-to value. This insight can be pushed a bit farther
- by allowing references to be *returned*, thus allowing function calls on the
- left hand side of an assignment stmt.
-
- ==============================================================================
-
- Q12: How can you reseat a reference to make it refer to a different object?
- A: Unlike a pointer, once a reference is bound to an object, it can NOT be
- `reseated' to another object. The reference itself isn't an object; you can't
- separate the reference from the referred-to-object. Ex: `&ref' is the address
- of the referred-to-object, not of the reference itself.
-
- ==============================================================================
-
- Q13: When should I use references, and when should I use pointers?
- A: Old line C programmers sometimes don't like references since the reference
- semantics they provide isn't *explicit* in the caller's code. After a bit of
- C++ experience, however, one quickly realizes this `information hiding' is an
- asset rather than a liability. In particular, reuse-centered OOP tends to
- migrate the level of abstraction away from the language of the machine toward
- the language of the problem.
-
- References are usually preferred over ptrs whenever you don't need `reseating'
- (see early question on `How can you reseat a reference'). This usually means
- that references are most useful in a class' public interface. References then
- typically appear on the skin of an object, and pointers on the inside.
-
- The exception to the above is where a function's parameter or return value
- needs a `sentinel' reference. This is usually best done by returning/taking a
- pointer, and giving the NULL pointer this special significance (references
- should always alias *objects*, not a dereferenced NULL ptr).
-
- ==============================================================================
-
- Q14: What are inline fns? What are their advantages? How are they declared?
- A: An inline function is a function which gets textually inserted by the
- compiler, much like a macro. Like macros, performance is improved by avoiding
- the overhead of the call itself, and (especially!) by the compiler being able
- to optimize *through* the call (`procedural integration'). Unlike macros,
- arguments to inline fns are always evaluated exactly once, so the `call' is
- semantically like a regular function call only faster. Also unlike macros,
- argument types are checked and necessary conversions are performed correctly.
-
- Beware that overuse of inline functions can cause code bloat, which can in
- turn have a negative performance impact in paging environments.
-
- They are declared by using the `inline' keyword when the function is defined:
- inline void f(int i, char c) { /*...*/ } //an inline function
- or by including the function definition itself within a class:
- class X {
- public:
- void f(int i, char c) { /*...*/ } //inline function within a class
- };
- or by defining the member function as `inline' outside the class:
- class X {
- public:
- void f(int i, char c);
- };
- //...
- inline void X::f(int i, char c) {/*...*/} //inline fn outside the class
-
- Generally speaking, a function cannot be defined as `inline' after it has been
- called. Inline functions should be defined in a header file, with `outlined'
- functions appearing in a `.C' file (or .cpp, etc; see question on file naming
- conventions).
-
- ==============================================================================
- SECTION 4: Constructors and destructors
- ==============================================================================
-
- Q15: What is a constructor? Why would I ever use one?
- A: Objects should establish and maintain their own internal coherence. The
- `maintaining' part is done by ensuring self-consistency is restored after any
- operation completes (ex: by incrementing the link count after adding a new link
- to a linked list). The part about `establishing coherence' is the job of a
- constructor.
-
- Constructors are like `init functions'; they build a valid object. The
- constructor turns a pile of incoherent arbitrary bits into a living object.
- Minimally it initializes any internally used fields that are needed, but it may
- also allocate resources (memory, files, semaphores, sockets, ...).
-
- A constructor is like a `factory': it builds objects from dust.
-
- `ctor' is a typical abbreviation for constructor.
-
- ==============================================================================
-
- Q16: How can I make a constructor call another constructor as a primitive?
- A: You can't. Use an `init()' member function instead (often `private:').
-
- ==============================================================================
-
- Q17: What are destructors really for? Why would I ever use them?
- A: Destructors are used to release any resources allocated by the object's
- constructor. Ex: a Lock class might lock a semaphore, and the destructor will
- release that semaphore. The usual `resource' being acquired in a constructor
- (and subsequently released in a destructor) is dynamically allocated memory.
-
- `dtor' is a typical abbreviation for destructor
-
- ==============================================================================
- SECTION 5: Operator overloading
- ==============================================================================
-
- Q18: What is operator overloading?
- A: Operator overloading allows the basic C/C++ operators to have user-defined
- meanings on user-defined types (classes). They are syntactic sugar for
- equivalent function calls; ex:
-
- class X {
- //...
- public:
- //...
- };
-
- X add(X, X); //a top-level function that adds two X's
- X mul(X, X); //a top-level function that multiplies two X's
-
- X f(X a, X b, X c)
- {
- return add(add(mul(a,b), mul(b,c)), mul(c,a));
- }
-
- Now merely replace `add' with `operator+' and `mul' with `operator*':
-
- X operator+(X, X); //a top-level function that adds two X's
- X operator*(X, X); //a top-level function that multiplies two X's
-
- X f(X a, X b, X c)
- {
- return a*b + b*c + c*a;
- }
-
- ==============================================================================
-
- Q19: What operators can/cannot be overloaded?
- A: Most can be overloaded. The only C operators that can't be are `.' and `?:'
- (and `sizeof', which is technically an operator). C++ adds a few of its own
- operators, most of which can be overloaded except `::' and `.*'.
-
- Here's an example of the subscript operator (it returns a reference).
- First withOUT operator overloading:
- class Vec {
- int data[100];
- public:
- int& elem(unsigned i) { if (i>99) error(); return data[i]; }
- };
-
- main()
- {
- Vec v;
- v.elem(10) = 42;
- v.elem(12) += v.elem(13);
- }
-
- Now simply replace `elem' with `operator[]':
- class Vec {
- int data[100];
- public:
- int& operator[](unsigned i) { if (i>99) error(); return data[i]; }
- }; //^^^^^^^^^^--formerly `elem'
-
- main()
- {
- Vec v;
- v[10] = 42;
- v[12] += v[13];
- }
-
- ==============================================================================
-
- Q20: Can I create a `**' operator for `to-the-power-of' operations?
- A: No.
-
- The names of, precedence of, associativity of, and arity of operators is fixed
- by the language. There is no `**' operator in C++, so you cannot create one
- for a class type.
-
- If you doubt the wisdom of this approach, consider the following code:
- x = y ** z;
- Looks like your power operator? Nope. z may be a ptr, so this is actually:
- x = y * (*z);
- Lexical analysis groups characters into tokens at the lowest level of the
- compiler's operations, so adding new operators would present an implementation
- nightmare (not to mention the increased maintenance cost to read the code!).
-
- Besides, operator overloading is just syntactic sugar for function calls. It
- does not add fundamental power to the language (although this particular
- syntactic sugar can be very sweet, it is not fundamentally necessary). I
- suggest you overload `pow(base,exponent)', for which a double precision version
- is provided by the ANSI-C <math.h> library.
-
- By the way: operator^ looks like a good candidate for to-the-power-of, but it
- has neither the proper precedence nor associativity.
-
- ==============================================================================
- SECTION 6: Friends
- ==============================================================================
-
- Q21: What is a `friend'?
- A: Friends can be either functions or other classes. The class grants friends
- access privileges. Normally a developer has political and technical control
- over both the class, its members, and its friends (that way you avoid political
- problems when you want to update a portion, since you don't have to get
- permission from the present owner of the other piece(s)).
-
- ==============================================================================
-
- Q22: Do `friends' violate encapsulation?
- A: Friends can be looked at three ways: (1) they are not class members and they
- therefore violate encapsulation of the class members by their mere existence,
- (2) a class' friends are absorbed into that class' encapsulation barrier, and
- (3) any time anyone wants to do anything tricky they textedit the header file
- and add a new friend so they can get right in there and fiddle 'dem bits.
-
- No one argues that (3) is a Good Thing, and for good reasons. The arguments for
- (1) always boil down to the rather arbitrary and somewhat naive view that a
- class' member functions `should' be the *only* functions inside a class'
- encapsulation barrier. I have not seen this view bear fruit by enhancing
- software quality. On the other hand, I have seen (2) bear fruit by lowering
- the *overall* coupling in a software system. Reason: friends can be used as
- `liaisons' to provide safe, screened access for the whole world, perhaps in a
- way that the class syntactically or semantically isn't able to do for itself.
-
- Conclusion: friend functions are merely a syntactic variant of a class' public
- access functions. When used in this manner, they don't violate encapsulation
- any more than a member function violates encapsulation. Thus a class' friends
- and members *are* the encapsulation barrier, as defined by the class itself.
-
- I've actually seen the `friends always violate encapsulation' view *destroy*
- encapsulation: programmers who have been taught that friends are inherently
- evil want to avoid them, but they have another class or fn that needs access to
- some internal detail in the class, so they provide a member fn which exposes
- the class' internal details to the PUBLIC! Private decisions should stay
- private, and only those inside your encapsulation barrier (your members,
- friends, and [for `protected' things] your subclasses) should have access.
-
- ==============================================================================
-
- Q23: What are some advantages/disadvantages of using friends?
- A: The advantage of using friends is generally syntactic. Ie: both a member fn
- and a friend are equally privileged (100% vested), but a friend function can be
- called like f(obj), where a member is called like obj.f(). When it's not for
- syntactic reasons (which is not a `bad' reason -- making an abstraction's
- syntax more readable lowers maintenance costs!), friends are used when two or
- more classes are designed to be more tightly coupled than you want for `joe
- public' (ex: you want to allow class `ListIter' to have more privilege with
- class `List' than you want to give to `main()').
-
- Friends have three disadvantages. The first disadvantage is that they add to
- the global namespace. In contrast, the namespace of member functions is buried
- within the class, reducing the chance for namespace collisions for functions.
-
- The second disadvantage is that they aren't inherited. That is, the
- `friendship privilege' isn't inherited. This is actually an advantage when it
- comes to encapsulation. Ex: I may declare you as my friend, but that doesn't
- mean I trust your kids.
-
- The third disadvantage is that they don't bind dynamically. Ie: they don't
- respond to polymorphism. There are no virtual friends; if you need one, have a
- friend call a hidden (usually `protected:') virtual member fn. Friends that
- take a ptr/ref to a class can also take a ptr/ref to a publically derived class
- object, so they act as if they are inherited, but the friendship *rights* are
- not inherited (the friend of a base has no special access to a class derived
- from that base).
-
- ==============================================================================
-
- Q24: What does it mean that `friendship is neither inherited nor transitive'?
- A: This is speaking of the access privileges granted when a class declares a
- friend.
-
- The access privilege of friendship is not inherited:
- * I may trust you, but I don't necessarily trust your kids.
- * My friends aren't necessarily friends of my kids.
- * Class `Base' declares f() to be a friend, but f() has no special access
- rights with class `Derived'.
-
- The access privilege of friendship is not transitive:
- * I may trust you, and you may trust Sam, but that doesn't necessarily mean
- that I trust Sam.
- * A friend of a friend is not necessarily a friend.
-
- ==============================================================================
-
- Q25: When would I use a member function as opposed to a friend function?
- A: Use a member when you can, and a friend when you have to.
-
- Like in real life, my family members have certain privileges that my friends do
- not have (ex: my family members inherit from me, but my friends do not, etc).
- To grant privileged access to a function, you need either a friend or a member;
- there is no additional loss of encapsulation one way or the other. Sometimes
- friends are syntactically better (ex: in class `X', friend fns allow the `X'
- param to be second, while members require it to be first). Another good use of
- friend functions are the binary infix arithmetic operators. Ex: `aComplex +
- aComplex' probably should be defined as a friend rather than a member, since
- you want to allow `aFloat + aComplex' as well (members don't allow promotion of
- the left hand arg, since that would change the class of the object that is the
- recipient of the member function invocation).
-
- ==============================================================================
- SECTION 7: Input/output via <iostream.h> and <stdio.h>
- ==============================================================================
-
- Q26: How can I provide printing for a `class X'?
- A: Provide a friend operator<<:
-
- class X {
- public:
- friend ostream& operator<< (ostream& o, const X& x)
- { return o << x.i; }
- //...
- private:
- int i; //just for illustration
- };
-
- We use a friend rather than a member since the `X' parameter is 2nd, not 1st.
- Input is similar, but the signature is:
- istream& operator>> (istream& i, X& x); //not `const X& x' !!
-
- ==============================================================================
-
- Q27: Why should I use <iostream.h> instead of the traditional <stdio.h>?
- A: See next question.
-
- ==============================================================================
-
- Q28: Printf/scanf weren't broken; why `fix' them with ugly shift operators?
- A: The overloaded shift operator syntax is strange at first sight, but it
- quickly grows on you. However syntax is just syntax; the real issues are
- deeper. Printf is arguably not broken, and scanf is perhaps livable despite
- being error prone, however both are limited with respect to what C++ I/O can
- do. C++ I/O (left/right shift) is, relative to C (printf/scanf):
- * type safe -- type of object being I/O'd is known statically by the compiler
- rather than via dynamically tested '%' fields
- * less error prone -- redundant info has greater chance to get things wrong
- C++ I/O has no redundant '%' tokens to get right
- * faster -- printf is basically an `interpreter' of a tiny language whose
- constructs mainly include '%' fields. the proper low-level routine is
- chosen at runtime based on these fields. C++ I/O picks these routines
- statically based on actual types of the args
- * extensible -- perhaps most important of all, the C++ I/O mechanism is
- extensible to new user-defined data types (imagine the chaos if
- everyone was simultaneously adding new incompatible '%' fields to
- printf and scanf?!). Remember: we want to make user-defined types
- (classes) look and act like `built-in' types.
- * subclassable -- ostream and istream (the C++ replacements for FILE*) are
- real classes, and hence subclassable. This means you can have other
- user defined things that look and act like streams, yet that do
- whatever strange and wonderful things you want. You automatically
- get to use the zillions of lines of I/O code written by users you
- don't even know, and they don't need to know about your `extended
- stream' class. Ex: you can have a `stream' that writes to a memory
- area (incore formatting provided by the standard class `strstream'),
- or you could have it use the stdio buffers, or [you name it...].
-
- --
- Marshall Cline
- --
- Marshall P. Cline, Ph.D. / Paradigm Shift Inc / PO Box 5108 / Potsdam NY 13676
- cline@parashift.com / 315-353-6100 / FAX: 315-353-6110
-