home *** CD-ROM | disk | FTP | other *** search
/ ftp.pasteur.org/FAQ/ / ftp-pasteur-org-FAQ.zip / FAQ / C++-faq / part4 < prev    next >
Text File  |  2000-03-01  |  54KB  |  1,528 lines

  1. Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!howland.erols.net!novia!nntp3.cerf.net!nntp2.cerf.net!news.cerf.net!not-for-mail
  2. From: mpcline@nic.cerf.net (Marshall Cline)
  3. Newsgroups: comp.lang.c++,comp.answers,news.answers,alt.comp.lang.learn.c-c++
  4. Subject: C++ FAQ (part 4 of 10)
  5. Followup-To: comp.lang.c++
  6. Date: 29 Feb 2000 20:06:42 GMT
  7. Organization: ATT Cerfnet
  8. Lines: 1507
  9. Approved: news-answers-request@mit.edu
  10. Distribution: world
  11. Expires: +1 month
  12. Message-ID: <89h8si$bts$1@news.cerf.net>
  13. Reply-To: cline@parashift.com (Marshall Cline)
  14. NNTP-Posting-Host: nic1.san.cerf.net
  15. X-Trace: news.cerf.net 951854802 12220 192.215.81.88 (29 Feb 2000 20:06:42 GMT)
  16. X-Complaints-To: abuse@cerf.net
  17. NNTP-Posting-Date: 29 Feb 2000 20:06:42 GMT
  18. Summary: Please read this before posting to comp.lang.c++
  19. Xref: senator-bedfellow.mit.edu comp.lang.c++:453822 comp.answers:39862 news.answers:178221 alt.comp.lang.learn.c-c++:40800
  20.  
  21. Archive-name: C++-faq/part4
  22. Posting-Frequency: monthly
  23. Last-modified: Feb 29, 2000
  24. URL: http://marshall-cline.home.att.net/cpp-faq-lite/
  25.  
  26. AUTHOR: Marshall Cline / cline@parashift.com / 972-931-9470
  27.  
  28. COPYRIGHT: This posting is part of "C++ FAQ Lite."  The entire "C++ FAQ Lite"
  29. document is Copyright(C)1991-2000 Marshall Cline, Ph.D., cline@parashift.com.
  30. All rights reserved.  Copying is permitted only under designated situations.
  31. For details, see section [1].
  32.  
  33. NO WARRANTY: THIS WORK IS PROVIDED ON AN "AS IS" BASIS.  THE AUTHOR PROVIDES NO
  34. WARRANTY WHATSOEVER, EITHER EXPRESS OR IMPLIED, REGARDING THE WORK, INCLUDING
  35. WARRANTIES WITH RESPECT TO ITS MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
  36. PURPOSE.
  37.  
  38. C++-FAQ-Lite != C++-FAQ-Book: This document, C++ FAQ Lite, is not the same as
  39. the C++ FAQ Book.  The book (C++ FAQs, Cline and Lomow, Addison-Wesley) is 500%
  40. larger than this document, and is available in bookstores.  For details, see
  41. section [3].
  42.  
  43. ==============================================================================
  44.  
  45. SECTION [10]: Constructors
  46.  
  47.  
  48. [10.1] What's the deal with constructors?
  49.  
  50. Constructors build objects from dust.
  51.  
  52. Constructors are like "init functions".  They turn a pile of arbitrary bits
  53. into a living object.  Minimally they initialize internally used fields.  They
  54. may also allocate resources (memory, files, semaphores, sockets, etc).
  55.  
  56. "ctor" is a typical abbreviation for constructor.
  57.  
  58. ==============================================================================
  59.  
  60. [10.2] Is there any difference between List x; and List x();?
  61.  
  62. A big difference!
  63.  
  64. Suppose that List is the name of some class.  Then function f() declares a
  65. local List object called x:
  66.  
  67.     void f()
  68.     {
  69.       List x;     // Local object named x (of class List)
  70.       // ...
  71.     }
  72.  
  73. But function g() declares a function called x() that returns a List:
  74.  
  75.     void g()
  76.     {
  77.       List x();   // Function named x (that returns a List)
  78.       // ...
  79.     }
  80.  
  81. ==============================================================================
  82.  
  83. [10.3] How can I make a constructor call another constructor as a primitive?
  84.  
  85. No way.
  86.  
  87. Dragons be here: if you call another constructor, the compiler initializes a
  88. temporary local object; it does not initialize this object.  You can combine
  89. both constructors by using a default parameter, or you can share their common
  90. code in a private init() member function.
  91.  
  92. ==============================================================================
  93.  
  94. [10.4] Is the default constructor for Fred always Fred::Fred()?
  95.  
  96. No.  A "default constructor" is a constructor that can be called with no
  97. arguments.  Thus a constructor that takes no arguments is certainly a default
  98. constructor:
  99.  
  100.     class Fred {
  101.     public:
  102.       Fred();   // Default constructor: can be called with no args
  103.       // ...
  104.     };
  105.  
  106. However it is possible (and even likely) that a default constructor can take
  107. arguments, provided they are given default values:
  108.  
  109.     class Fred {
  110.     public:
  111.       Fred(int i=3, int j=5);   // Default constructor: can be called with no args
  112.       // ...
  113.     };
  114.  
  115. ==============================================================================
  116.  
  117. [10.5] Which constructor gets called when I create an array of Fred objects?
  118.  
  119. Fred's default constructor[10.4] (except as discussed below).
  120.  
  121. There is no way to tell the compiler to call a different constructor (except as
  122. discussed below).  If your class Fred doesn't have a default constructor[10.4],
  123. attempting to create an array of Fred objects is trapped as an error at compile
  124. time.
  125.  
  126.     class Fred {
  127.     public:
  128.       Fred(int i, int j);
  129.       // ... assume there is no default constructor[10.4] in class Fred ...
  130.     };
  131.  
  132.     int main()
  133.     {
  134.       Fred a[10];               // ERROR: Fred doesn't have a default constructor
  135.       Fred* p = new Fred[10];   // ERROR: Fred doesn't have a default constructor
  136.     }
  137.  
  138. However if you are creating an STL[32.1] vector<Fred> rather than an array of
  139. Fred (which you probably should be doing anyway since arrays are evil[21.5]),
  140. you don't have to have a default constructor in class Fred, since you can give
  141. the vector a Fred object to be used to initialize the elements:
  142.  
  143.     #include <vector>
  144.     using namespace std;
  145.  
  146.     int main()
  147.     {
  148.       vector<Fred> a(10, Fred(5,7));
  149.       // The 10 Fred objects in vector a will be initialized with Fred(5,7).
  150.       // ...
  151.     }
  152.  
  153. Even though you ought to use a vector rather than an array, there are times
  154. when an array might be the right thing to do, and for those, there is the
  155. "explicit initialization of arrays" syntax.  Here's how it looks:
  156.  
  157.     class Fred {
  158.     public:
  159.       Fred(int i, int j);
  160.       // ... assume there is no default constructor[10.4] in class Fred ...
  161.     };
  162.  
  163.     int main()
  164.     {
  165.       Fred a[10] = {
  166.         Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7),
  167.         Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7)
  168.       };
  169.  
  170.       // The 10 Fred objects in array a will be initialized with Fred(5,7).
  171.       // ...
  172.     }
  173.  
  174. Of course you don't have to do Fred(5,7) for every entry -- you can put in any
  175. numbers you want, even parameters or other variables.  The point is that this
  176. syntax is (a) doable but (b) not as nice as the vector syntax.  Remember this:
  177. arrays are evil[21.5] -- unless there is a compelling reason to use an array,
  178. use a vector instead.
  179.  
  180. ==============================================================================
  181.  
  182. [10.6] Should my constructors use "initialization lists" or "assignment"?
  183.  
  184. Constructors should initialize all member objects in the initialization list.
  185.  
  186. For example, this constructor initializes member object x_ using an
  187. initialization list: Fred::Fred() : x_(whatever) { }.  From a performance
  188. perspective, it is important to note that the whatever expression doesn't
  189. automatically cause a separate object to be created and copied into x_: if the
  190. types are the same the result of ...whatever... will be constructed directly
  191. inside x_.
  192.  
  193. In contrast the following constructor uses assignment:
  194. Fred::Fred() { x_ = whatever; }.  In this case the expression whatever causes a
  195. separate, temporary object to be created, and this temporary object is passed
  196. into the x_ object's assignment operator, then is destructed at the ;.  That's
  197. inefficient.
  198.  
  199. There's another source of inefficiency as well: in the second (assignment)
  200. case, the object's default constructor (implicitly called before the
  201. constructor body's "{") might, for example, allocate some default amount of
  202. memory or open some default file.  All this work could be for naught if the
  203. whatever expression and/or assignment operator causes the object to close that
  204. file and/or release that memory (e.g., if the default constructor didn't
  205. allocate a large enough pool of memory or if it opened the wrong file).
  206.  
  207. Conclusion: All other things being equal, your code will run faster if you use
  208. initialization lists rather than assignment.
  209.  
  210. ==============================================================================
  211.  
  212. [10.7] Should you use the this pointer in the constructor? [NEW!]
  213.  
  214. [Recently created with the help of Jim Hyslop (on 1/00).]
  215.  
  216. Some people feel you should not use the this pointer in a constructor because
  217. the this object is not fully formed yet.  However you can use this in the
  218. constructor (in the {body} and even in the initialization list[10.6]) if you
  219. are careful.
  220.  
  221. Once you're in the {body} of the constructor, it's easy to imagine that you can
  222. use the this pointer since all the base class subobjects and the member objects
  223. will already have been fully constructed.  However even there you must be
  224. careful.  For example, if you call a virtual member function (or call some
  225. other function which turns around and calls a virtual member function) on the
  226. this object, you may not get what you want[23.1].
  227.  
  228. But you are even allowed to use the this pointer in the constructor's
  229. initializer list[10.6], provided you are very careful that you don't touch any
  230. member objects or base class subobjects that have not yet been constructed.
  231. This requires a rather intimate knowledge of the order that things happen in a
  232. constructor -- you have been warned.  The safest thing to do is store the value
  233. of the this pointer somewhere and use that pointer later.
  234.  
  235. ==============================================================================
  236.  
  237. [10.8] What is the "Named Constructor Idiom"?
  238.  
  239. A technique that provides more intuitive and/or safer construction operations
  240. for users of your class.
  241.  
  242. The problem is that constructors always have the same name as the class.
  243. Therefore the only way to differentiate between the various constructors of a
  244. class is by the parameter list.  But if there are lots of constructors, the
  245. differences between the constructors becomes somewhat subtle and error prone.
  246.  
  247. With the Named Constructor Idiom, you declare all the class's constructors in
  248. the private: or protected: sections, and you provide public static methods that
  249. return an object.  These static methods are the so-called "Named Constructors."
  250. In general there is one such static method for each different way to construct
  251. an object.
  252.  
  253. For example, suppose we are building a Point class that represents a position
  254. on the X-Y plane.  Turns out there are two common ways to specify a 2-space
  255. coordinate: rectangular coordinates (X+Y), polar coordinates (Radius+Angle).
  256. (Don't worry if you can't remember these; the point isn't the particulars of
  257. coordinate systems; the point is that there are several ways to create a Point
  258. object).  Unfortunately the parameters for these two coordinate systems are the
  259. same: two floats.  This would create an ambiguity error in the overloaded
  260. constructors:
  261.  
  262.     class Point {
  263.     public:
  264.       Point(float x, float y);     // Rectangular coordinates
  265.       Point(float r, float a);     // Polar coordinates (radius and angle)
  266.       // ERROR: Overload is Ambiguous: Point::Point(float,float)
  267.     };
  268.  
  269.     int main()
  270.     {
  271.       Point p = Point(5.7, 1.2);   // Ambiguous: Which coordinate system?
  272.     }
  273.  
  274. One way to solve this ambiguity is to use the Named Constructor Idiom:
  275.  
  276.     #include <math.h>              // To get sin() and cos()
  277.  
  278.     class Point {
  279.     public:
  280.       static Point rectangular(float x, float y);      // Rectangular coord's
  281.       static Point polar(float radius, float angle);   // Polar coordinates
  282.       // These static methods are the so-called "named constructors"
  283.       // ...
  284.     private:
  285.       Point(float x, float y);     // Rectangular coordinates
  286.       float x_, y_;
  287.     };
  288.  
  289.     inline Point::Point(float x, float y)
  290.     : x_(x), y_(y) { }
  291.  
  292.     inline Point Point::rectangular(float x, float y)
  293.     { return Point(x, y); }
  294.  
  295.     inline Point Point::polar(float radius, float angle)
  296.     { return Point(radius*cos(angle), radius*sin(angle)); }
  297.  
  298. Now the users of Point have a clear and unambiguous syntax for creating Points
  299. in either coordinate system:
  300.  
  301.     int main()
  302.     {
  303.       Point p1 = Point::rectangular(5.7, 1.2);   // Obviously rectangular
  304.       Point p2 = Point::polar(5.7, 1.2);         // Obviously polar
  305.     }
  306.  
  307. Make sure your constructors are in the protected: section if you expect Fred to
  308. have derived classes.
  309.  
  310. The Named Constructor Idiom can also be used to make sure your objects are
  311. always created via new[16.19].
  312.  
  313. ==============================================================================
  314.  
  315. [10.9] Why can't I initialize my static member data in my constructor's
  316.        initialization list?
  317.  
  318. Because you must explicitly define your class's static data members.
  319.  
  320. Fred.h:
  321.  
  322.     class Fred {
  323.     public:
  324.       Fred();
  325.       // ...
  326.     private:
  327.       int i_;
  328.       static int j_;
  329.     };
  330.  
  331. Fred.cpp (or Fred.C or whatever):
  332.  
  333.     Fred::Fred()
  334.       : i_(10)  // OK: you can (and should) initialize member data this way
  335.         j_(42)  // Error: you cannot initialize static member data like this
  336.     {
  337.       // ...
  338.     }
  339.  
  340.     // You must define static data members this way:
  341.     int Fred::j_ = 42;
  342.  
  343. ==============================================================================
  344.  
  345. [10.10] Why are classes with static data members getting linker errors?
  346.  
  347. Because static data members must be explicitly defined in exactly one
  348. compilation unit[10.9].  If you didn't do this, you'll probably get an
  349. "undefined external" linker error.  For example:
  350.  
  351.     // Fred.h
  352.  
  353.     class Fred {
  354.     public:
  355.       // ...
  356.     private:
  357.       static int j_;   // Declares static data member Fred::j_
  358.       // ...
  359.     };
  360.  
  361. The linker will holler at you ("Fred::j_ is not defined") unless you define (as
  362. opposed to merely declare) Fred::j_ in (exactly) one of your source files:
  363.  
  364.     // Fred.cpp
  365.  
  366.     #include "Fred.h"
  367.  
  368.     int Fred::j_ = some_expression_evaluating_to_an_int;
  369.  
  370.     // Alternatively, if you wish to use the implicit 0 value for static ints:
  371.     // int Fred::j_;
  372.  
  373. The usual place to define static data members of class Fred is file Fred.cpp
  374. (or Fred.C or whatever source file extension you use).
  375.  
  376. ==============================================================================
  377.  
  378. [10.11] What's the "static initialization order fiasco"?
  379.  
  380. A subtle way to kill your project.
  381.  
  382. The static initialization order fiasco is a very subtle and commonly
  383. misunderstood aspect of C++.  Unfortunately it's very hard to detect -- the
  384. errors occur before main() begins.
  385.  
  386. In short, suppose you have two static objects x and y which exist in separate
  387. source files, say x.cpp and y.cpp.  Suppose further that the constructor for
  388. the y object calls some method on the x object.
  389.  
  390. That's it.  It's that simple.
  391.  
  392. The tragedy is that you have a 50%-50% chance of dying.  If the compilation
  393. unit for x.cpp happens to get initialized first, all is well.  But if the
  394. compilation unit for y.cpp get initialized first, then y's constructor will get
  395. run before x's constructor, and you're toast.  I.e., y's constructor will call
  396. a method on the x object, yet the x object hasn't yet been constructed.
  397.  
  398. I hear they're hiring down at McDonalds.  Enjoy your new job flipping burgers.
  399.  
  400. If you think it's "exciting" to play Russian Roulette with live rounds in half
  401. the chambers, you can stop reading here.  On the other hand if you like to
  402. improve your chances of survival by preventing disasters in a systematic way,
  403. you probably want to read the next FAQ[10.12].
  404.  
  405. Note: The static initialization order fiasco does not apply to
  406. builtin/intrinsic types like int or char*.  For example if you create a static
  407. float object, there is never a problem with static initialization order.  The
  408. only time the static initialization order is truly a fiasco is when your static
  409. or global objects have a constructor.
  410.  
  411. ==============================================================================
  412.  
  413. [10.12] How do I prevent the "static initialization order fiasco"?
  414.  
  415. Use the "construct on first use" idiom, which simply means to wrap your static
  416. object inside a function.
  417.  
  418. For example, suppose you have two classes, Fred and Barney.  There is a global
  419. Fred object called x, and a global Barney object called y.  Barney's
  420. constructor invokes the goBowling() method on the x object.  The file x.cpp
  421. defines the x object:
  422.  
  423.     // File x.cpp
  424.     #include "Fred.hpp"
  425.     Fred x;
  426.  
  427. The file y.cpp defines the y object:
  428.  
  429.     // File y.cpp
  430.     #include "Barney.hpp"
  431.     Barney y;
  432.  
  433. For completeness the Barney constructor might look something like this:
  434.  
  435.     // File Barney.cpp
  436.     #include "Barney.hpp"
  437.  
  438.     Barney::Barney()
  439.     {
  440.       // ...
  441.       x.goBowling();
  442.       // ...
  443.     }
  444.  
  445. As described above[10.11], the disaster occurs if y is constructed before x,
  446. which happens 50% of the time since they're in different source files.
  447.  
  448. There are many solutions to this problem, but a very simple and completely
  449. portable solution is to replace the global Fred object, x, with a global
  450. function, x(), that returns the Fred object by reference.
  451.  
  452.     // File x.cpp
  453.  
  454.     #include "Fred.hpp"
  455.  
  456.     Fred& x()
  457.     {
  458.       static Fred* ans = new Fred();
  459.       return *ans;
  460.     }
  461.  
  462. Since static local objects are constructed the first time control flows over
  463. their declaration (only), the above new Fred() statement will only happen once:
  464. the first time x() is called.  Every subsequent call will return the same Fred
  465. object (the one pointed to by ans).  Then all you do is change your usages of x
  466. to x():
  467.  
  468.     // File Barney.cpp
  469.     #include "Barney.hpp"
  470.  
  471.     Barney::Barney()
  472.     {
  473.       // ...
  474.       x().goBowling();
  475.       // ...
  476.     }
  477.  
  478. This is called the Construct On First Use Idiom because it does just that: the
  479. global Fred object is constructed on its first use.
  480.  
  481. The downside of this approach is that the Fred object is never destructed.  The
  482. C++ FAQ Book has a second technique that answers this concern (but at the cost
  483. of opening a "static de-initialization order fiasco").
  484.  
  485. Note: You don't have to do this for builtin/intrinsic types like int or char*.
  486. For example if you create a static or global float object, there is no need to
  487. wrap it within a function.  The only time the static initialization order is
  488. truly a fiasco is when your static or global objects have a constructor.
  489.  
  490. ==============================================================================
  491.  
  492. [10.13] How do I prevent the "static initialization order fiasco" for my static
  493.         data members?
  494.  
  495. Just use the same technique just described[10.12], but this time use a static
  496. member function rather than a global function.
  497.  
  498. Suppose you have a class X that has a static Fred object:
  499.  
  500.     // File X.hpp
  501.  
  502.     class X {
  503.     public:
  504.       // ...
  505.  
  506.     private:
  507.       static Fred x_;
  508.     };
  509.  
  510. Naturally this static member is initialized separately:
  511.  
  512.     // File X.cpp
  513.  
  514.     #include "X.hpp"
  515.  
  516.     Fred X::x_;
  517.  
  518. Naturally also the Fred object will be used in one or more of X's methods:
  519.  
  520.     void X::someMethod()
  521.     {
  522.       x_.goBowling();
  523.     }
  524.  
  525. But now the "disaster scenario" is if someone somewhere somehow calls this
  526. method before the Fred object gets constructed.  For example, if someone else
  527. creates a static X object and invokes its someMethod() method during static
  528. initialization, then you're at the mercy of the compiler as to whether the
  529. compiler will construct X::x_ before or after the someMethod() is called.
  530. (Note that the ANSI/ISO C++ committee is working on this problem, but compilers
  531. aren't yet generally available that handle these changes; watch this space for
  532. an update in the future.)
  533.  
  534. In any event, it's always portable and safe to change the X::x_ static data
  535. member into a static member function:
  536.  
  537.     // File X.hpp
  538.  
  539.     class X {
  540.     public:
  541.       // ...
  542.  
  543.     private:
  544.       static Fred& x();
  545.     };
  546.  
  547. Naturally this static member is initialized separately:
  548.  
  549.     // File X.cpp
  550.  
  551.     #include "X.hpp"
  552.  
  553.     Fred& X::x()
  554.     {
  555.       static Fred* ans = new Fred();
  556.       return *ans;
  557.     }
  558.  
  559. Then you simply change any usages of x_ to x():
  560.  
  561.     void X::someMethod()
  562.     {
  563.       x().goBowling();
  564.     }
  565.  
  566. If you're super performance sensitive and you're concerned about the overhead
  567. of an extra function call on each invocation of X::someMethod() you can set up
  568. a static Fred& instead.  As you recall, static local are only initialized once
  569. (the first time control flows over their declaration), so this will call X::x()
  570. only once: the first time X::someMethod() is called:
  571.  
  572.     void X::someMethod()
  573.     {
  574.       static Fred& x = X::x();
  575.       x.goBowling();
  576.     }
  577.  
  578. Note: You don't have to do this for builtin/intrinsic types like int or char*.
  579. For example if you create a static or global float object, there is no need to
  580. wrap it within a function.  The only time the static initialization order is
  581. truly a fiasco is when your static or global objects have a constructor.
  582.  
  583. ==============================================================================
  584.  
  585. [10.14] How can I handle a constructor that fails?
  586.  
  587. Throw an exception.  See [17.1] for details.
  588.  
  589. ==============================================================================
  590.  
  591. SECTION [11]: Destructors
  592.  
  593.  
  594. [11.1] What's the deal with destructors?
  595.  
  596. A destructor gives an object its last rites.
  597.  
  598. Destructors are used to release any resources allocated by the object.  E.g.,
  599. class Lock might lock a semaphore, and the destructor will release that
  600. semaphore.  The most common example is when the constructor uses new, and the
  601. destructor uses delete.
  602.  
  603. Destructors are a "prepare to die" member function.  They are often abbreviated
  604. "dtor".
  605.  
  606. ==============================================================================
  607.  
  608. [11.2] What's the order that local objects are destructed?
  609.  
  610. In reverse order of construction: First constructed, last destructed.
  611.  
  612. In the following example, b's destructor will be executed first, then a's
  613. destructor:
  614.  
  615.     void userCode()
  616.     {
  617.       Fred a;
  618.       Fred b;
  619.       // ...
  620.     }
  621.  
  622. ==============================================================================
  623.  
  624. [11.3] What's the order that objects in an array are destructed?
  625.  
  626. In reverse order of construction: First constructed, last destructed.
  627.  
  628. In the following example, the order for destructors will be a[9], a[8], ...,
  629. a[1], a[0]:
  630.  
  631.     void userCode()
  632.     {
  633.       Fred a[10];
  634.       // ...
  635.     }
  636.  
  637. ==============================================================================
  638.  
  639. [11.4] Can I overload the destructor for my class?
  640.  
  641. No.
  642.  
  643. You can have only one destructor for a class Fred.  It's always called
  644. Fred::~Fred().  It never takes any parameters, and it never returns anything.
  645.  
  646. You can't pass parameters to the destructor anyway, since you never explicitly
  647. call a destructor[11.5] (well, almost never[11.10]).
  648.  
  649. ==============================================================================
  650.  
  651. [11.5] Should I explicitly call a destructor on a local variable?
  652.  
  653. No!
  654.  
  655. The destructor will get called again at the close } of the block in which the
  656. local was created.  This is a guarantee of the language; it happens
  657. automagically; there's no way to stop it from happening.  But you can get
  658. really bad results from calling a destructor on the same object a second time!
  659. Bang! You're dead!
  660.  
  661. ==============================================================================
  662.  
  663. [11.6] What if I want a local to "die" before the close } of the scope in which
  664.        it was created? Can I call a destructor on a local if I really want to?
  665.  
  666. No! [For context, please read the previous FAQ[11.5]].
  667.  
  668. Suppose the (desirable) side effect of destructing a local File object is to
  669. close the File.  Now suppose you have an object f of a class File and you want
  670. File f to be closed before the end of the scope (i.e., the }) of the scope of
  671. object f:
  672.  
  673.     void someCode()
  674.     {
  675.       File f;
  676.  
  677.       // ... [This code that should execute when f is still open] ...
  678.  
  679.       // <-- We want the side-effect of f's destructor here!
  680.  
  681.       // ... [This code that should execute after f is closed] ...
  682.     }
  683.  
  684. There is a simple solution to this problem[11.7].  But in the mean time,
  685. remember: Do not explicitly call the destructor![11.5]
  686.  
  687. ==============================================================================
  688.  
  689. [11.7] OK, OK already; I won't explicitly call the destructor of a local; but
  690.        how do I handle the above situation?
  691.  
  692. [For context, please read the previous FAQ[11.6]].
  693.  
  694. Simply wrap the extent of the lifetime of the local in an artificial block {
  695. ... }:
  696.  
  697.     void someCode()
  698.     {
  699.       {
  700.         File f;
  701.         // ... [This code will execute when f is still open] ...
  702.       }
  703.     // ^-- f's destructor will automagically be called here!
  704.  
  705.       // ... [This code will execute after f is closed] ...
  706.     }
  707.  
  708. ==============================================================================
  709.  
  710. [11.8] What if I can't wrap the local in an artificial block? [UPDATED!]
  711.  
  712. [Recently added the note about constructors at the end (on 3/00).]
  713.  
  714. Most of the time, you can limit the lifetime of a local by wrapping the local
  715. in an artificial block ({ ...  })[11.7].  But if for some reason you can't do
  716. that, add a member function that has a similar effect as the destructor.  But
  717. do not call the destructor itself!
  718.  
  719. For example, in the case of class File, you might add a close() method.
  720. Typically the destructor will simply call this close() method.  Note that the
  721. close() method will need to mark the File object so a subsequent call won't
  722. re-close an already-closed File.  E.g., it might set the fileHandle_ data
  723. member to some nonsensical value such as -1, and it might check at the
  724. beginning to see if the fileHandle_ is already equal to -1:
  725.  
  726.     class File {
  727.     public:
  728.       void close();
  729.       ~File();
  730.       // ...
  731.     private:
  732.       int fileHandle_;   // fileHandle_ >= 0 if/only-if it's open
  733.     };
  734.  
  735.     File::~File()
  736.     {
  737.       close();
  738.     }
  739.  
  740.     void File::close()
  741.     {
  742.       if (fileHandle_ >= 0) {
  743.         // ... [Perform some operating-system call to close the file] ...
  744.         fileHandle_ = -1;
  745.       }
  746.     }
  747.  
  748. Note that the other File methods may also need to check if the fileHandle_ is
  749. -1 (i.e., check if the File is closed).
  750.  
  751. Note also that any constructors that don't actually open a file should set
  752. fileHandle_ to -1.
  753.  
  754. ==============================================================================
  755.  
  756. [11.9] But can I explicitly call a destructor if I've allocated my object with
  757.        new?
  758.  
  759. Probably not.
  760.  
  761. Unless you used placement new[11.10], you should simply delete the object
  762. rather than explicitly calling the destructor.  For example, suppose you
  763. allocated the object via a typical new expression:
  764.  
  765.     Fred* p = new Fred();
  766.  
  767. Then the destructor Fred::~Fred() will automagically get called when you delete
  768. it via:
  769.  
  770.     delete p;  // Automagically calls p->~Fred()
  771.  
  772. You should not explicitly call the destructor, since doing so won't release the
  773. memory that was allocated for the Fred object itself.  Remember: delete p does
  774. two things[16.8]: it calls the destructor and it deallocates the memory.
  775.  
  776. ==============================================================================
  777.  
  778. [11.10] What is "placement new" and why would I use it?
  779.  
  780. There are many uses of placement new.  The simplest use is to place an object
  781. at a particular location in memory.  This is done by supplying the place as a
  782. pointer parameter to the new part of a new expression:
  783.  
  784.     #include <new.h>      // Must #include this to use "placement new"
  785.     #include "Fred.h"     // Declaration of class Fred
  786.  
  787.     void someCode()
  788.     {
  789.       char memory[sizeof(Fred)];     // Line #1
  790.       void* place = memory;          // Line #2
  791.  
  792.       Fred* f = new(place) Fred();   // Line #3 (see "DANGER" below)
  793.       // The pointers f and place will be equal
  794.  
  795.       // ...
  796.     }
  797.  
  798. Line #1 creates an array of sizeof(Fred) bytes of memory, which is big enough
  799. to hold a Fred object.  Line #2 creates a pointer place that points to the
  800. first byte of this memory (experienced C programmers will note that this step
  801. was unnecessary; it's there only to make the code more obvious).  Line #3
  802. essentially just calls the constructor Fred::Fred().  The this pointer in the
  803. Fred constructor will be equal to place.  The returned pointer f will therefore
  804. be equal to place.
  805.  
  806. ADVICE: Don't use this "placement new" syntax unless you have to.  Use it only
  807. when you really care that an object is placed at a particular location in
  808. memory.  For example, when your hardware has a memory-mapped I/O timer device,
  809. and you want to place a Clock object at that memory location.
  810.  
  811. DANGER: You are taking sole responsibility that the pointer you pass to the
  812. "placement new" operator points to a region of memory that is big enough and is
  813. properly aligned for the object type that you're creating.  Neither the
  814. compiler nor the run-time system make any attempt to check whether you did this
  815. right.  If your Fred class needs to be aligned on a 4 byte boundary but you
  816. supplied a location that isn't properly aligned, you can have a serious
  817. disaster on your hands (if you don't know what "alignment" means, please don't
  818. use the placement new syntax).  You have been warned.
  819.  
  820. You are also solely responsible for destructing the placed object.  This is
  821. done by explicitly calling the destructor:
  822.  
  823.     void someCode()
  824.     {
  825.       char memory[sizeof(Fred)];
  826.       void* p = memory;
  827.       Fred* f = new(p) Fred();
  828.       // ...
  829.       f->~Fred();   // Explicitly call the destructor for the placed object
  830.     }
  831.  
  832. This is about the only time you ever explicitly call a destructor.
  833.  
  834. ==============================================================================
  835.  
  836. [11.11] When I write a destructor, do I need to explicitly call the destructors
  837.         for my member objects?
  838.  
  839. No.  You never need to explicitly call a destructor (except with placement
  840. new[11.10]).
  841.  
  842. A class's destructor (whether or not you explicitly define one) automagically
  843. invokes the destructors for member objects.  They are destroyed in the reverse
  844. order they appear within the declaration for the class.
  845.  
  846.     class Member {
  847.     public:
  848.       ~Member();
  849.       // ...
  850.     };
  851.  
  852.     class Fred {
  853.     public:
  854.       ~Fred();
  855.       // ...
  856.     private:
  857.       Member x_;
  858.       Member y_;
  859.       Member z_;
  860.     };
  861.  
  862.     Fred::~Fred()
  863.     {
  864.       // Compiler automagically calls z_.~Member()
  865.       // Compiler automagically calls y_.~Member()
  866.       // Compiler automagically calls x_.~Member()
  867.     }
  868.  
  869. ==============================================================================
  870.  
  871. [11.12] When I write a derived class's destructor, do I need to explicitly call
  872.         the destructor for my base class?
  873.  
  874. No.  You never need to explicitly call a destructor (except with placement
  875. new[11.10]).
  876.  
  877. A derived class's destructor (whether or not you explicitly define one)
  878. automagically invokes the destructors for base class subobjects.  Base classes
  879. are destructed after member objects.  In the event of multiple inheritance,
  880. direct base classes are destructed in the reverse order of their appearance in
  881. the inheritance list.
  882.  
  883.     class Member {
  884.     public:
  885.       ~Member();
  886.       // ...
  887.     };
  888.  
  889.     class Base {
  890.     public:
  891.       virtual ~Base();     // A virtual destructor[20.4]
  892.       // ...
  893.     };
  894.  
  895.     class Derived : public Base {
  896.     public:
  897.       ~Derived();
  898.       // ...
  899.     private:
  900.       Member x_;
  901.     };
  902.  
  903.     Derived::~Derived()
  904.     {
  905.       // Compiler automagically calls x_.~Member()
  906.       // Compiler automagically calls Base::~Base()
  907.     }
  908.  
  909. Note: Order dependencies with virtual inheritance are trickier.  If you are
  910. relying on order dependencies in a virtual inheritance hierarchy, you'll need a
  911. lot more information than is in this FAQ.
  912.  
  913. ==============================================================================
  914.  
  915. SECTION [12]: Assignment operators
  916.  
  917.  
  918. [12.1] What is "self assignment"? [UPDATED!]
  919.  
  920. [Recently changed "knowning" to "knowing" thanks to Stan Brown (on 1/00).]
  921.  
  922. Self assignment is when someone assigns an object to itself.  For example,
  923.  
  924.     #include "Fred.hpp"    // Declares class Fred
  925.  
  926.     void userCode(Fred& x)
  927.     {
  928.       x = x;   // Self-assignment
  929.     }
  930.  
  931. Obviously no one ever explicitly does a self assignment like the above, but
  932. since more than one pointer or reference can point to the same object
  933. (aliasing), it is possible to have self assignment without knowing it:
  934.  
  935.     #include "Fred.hpp"    // Declares class Fred
  936.  
  937.     void userCode(Fred& x, Fred& y)
  938.     {
  939.       x = y;   // Could be self-assignment if &x == &y
  940.     }
  941.  
  942.     int main()
  943.     {
  944.       Fred z;
  945.       userCode(z, z);
  946.     }
  947.  
  948. ==============================================================================
  949.  
  950. [12.2] Why should I worry about "self assignment"?
  951.  
  952. If you don't worry about self assignment[12.1], you'll expose your users to
  953. some very subtle bugs that have very subtle and often disastrous symptoms.  For
  954. example, the following class will cause a complete disaster in the case of
  955. self-assignment:
  956.  
  957.     class Wilma { };
  958.  
  959.     class Fred {
  960.     public:
  961.       Fred()                : p_(new Wilma())      { }
  962.       Fred(const Fred& f)   : p_(new Wilma(*f.p_)) { }
  963.      ~Fred()                { delete p_; }
  964.       Fred& operator= (const Fred& f)
  965.         {
  966.           // Bad code: Doesn't handle self-assignment!
  967.           delete p_;                // Line #1
  968.           p_ = new Wilma(*f.p_);    // Line #2
  969.           return *this;
  970.         }
  971.     private:
  972.       Wilma* p_;
  973.     };
  974.  
  975. If someone assigns a Fred object to itself, line #1 deletes both this->p_ and
  976. f.p_ since *this and f are the same object.  But line #2 uses *f.p_, which is
  977. no longer a valid object.  This will likely cause a major disaster.
  978.  
  979. The bottom line is that you the author of class Fred are responsible to make
  980. sure self-assignment on a Fred object is innocuous[12.3].  Do not assume that
  981. users won't ever do that to your objects.  It is your fault if your object
  982. crashes when it gets a self-assignment.
  983.  
  984. Aside: the above Fred::operator= (const Fred&) has a second problem:     If an
  985. exception is thrown[17] while evaluating new Wilma(*f.p_) (e.g., an
  986. out-of-memory     exception[16.5] or an exception in Wilma's copy
  987.     constructor[17.1]), this->p_ will be a dangling pointer -- it will
  988.     point to memory that is no longer valid.  This can be solved by allocating
  989. the     new objects before deleting the old objects.
  990.  
  991. ==============================================================================
  992.  
  993. [12.3] OK, OK, already; I'll handle self-assignment.  How do I do it?
  994.        [UPDATED!]
  995.  
  996. [Recently reworded the last paragraph thanks to Stan Brown (on 1/00).]
  997.  
  998. You should worry about self assignment every time you create a class[12.2].
  999. This does not mean that you need to add extra code to all your classes: as long
  1000. as your objects gracefully handle self assignment, it doesn't matter whether
  1001. you had to add extra code or not.
  1002.  
  1003. If you do need to add extra code to your assignment operator, here's a simple
  1004. and effective technique:
  1005.  
  1006.     Fred& Fred::operator= (const Fred& f)
  1007.     {
  1008.       if (this == &f) return *this;   // Gracefully handle self assignment[12.1]
  1009.  
  1010.       // Put the normal assignment duties here...
  1011.  
  1012.       return *this;
  1013.     }
  1014.  
  1015. This explicit test isn't always necessary.  For example, if you were to fix the
  1016. assignment operator in the previous FAQ[12.2] to handle exceptions thrown by
  1017. new[16.5] and/or exceptions thrown by the copy constructor[17.1] of class
  1018. Wilma, you might produce the following code.  Note that this code has the
  1019. (pleasant) side effect of automatically handling self assignment as well:
  1020.  
  1021.     Fred& Fred::operator= (const Fred& f)
  1022.     {
  1023.       // This code gracefully (albeit implicitly) handles self assignment[12.1]
  1024.       Wilma* tmp = new Wilma(*f.p_);   // It would be OK if an exception[17] got thrown here
  1025.       delete p_;
  1026.       p_ = tmp;
  1027.       return *this;
  1028.     }
  1029.  
  1030. In cases like the previous example (where self assignment is harmless but
  1031. inefficient), some programmers want to add "if (this == &f) return *this;" to
  1032. improve the efficiency of self assignment.  This is generally the wrong
  1033. tradeoff.  If self assignment only occurs once in a thousand times, the if
  1034. would waste cycles 99.9% of the time.
  1035.  
  1036. ==============================================================================
  1037.  
  1038. SECTION [13]: Operator overloading
  1039.  
  1040.  
  1041. [13.1] What's the deal with operator overloading?
  1042.  
  1043. It allows you to provide an intuitive interface to users of your class.
  1044.  
  1045. Operator overloading allows C/C++ operators to have user-defined meanings on
  1046. user-defined types (classes).  Overloaded operators are syntactic sugar for
  1047. function calls:
  1048.  
  1049.     class Fred {
  1050.     public:
  1051.       // ...
  1052.     };
  1053.  
  1054.     #if 0
  1055.  
  1056.       // Without operator overloading:
  1057.       Fred add(Fred, Fred);
  1058.       Fred mul(Fred, Fred);
  1059.  
  1060.       Fred f(Fred a, Fred b, Fred c)
  1061.       {
  1062.         return add(add(mul(a,b), mul(b,c)), mul(c,a));    // Yuk...
  1063.       }
  1064.  
  1065.     #else
  1066.  
  1067.       // With operator overloading:
  1068.       Fred operator+ (Fred, Fred);
  1069.       Fred operator* (Fred, Fred);
  1070.  
  1071.       Fred f(Fred a, Fred b, Fred c)
  1072.       {
  1073.         return a*b + b*c + c*a;
  1074.       }
  1075.  
  1076.     #endif
  1077.  
  1078. ==============================================================================
  1079.  
  1080. [13.2] What are the benefits of operator overloading?
  1081.  
  1082. By overloading standard operators on a class, you can exploit the intuition of
  1083. the users of that class.  This lets users program in the language of the
  1084. problem domain rather than in the language of the machine.
  1085.  
  1086. The ultimate goal is to reduce both the learning curve and the defect rate.
  1087.  
  1088. ==============================================================================
  1089.  
  1090. [13.3] What are some examples of operator overloading?
  1091.  
  1092. Here are a few of the many examples of operator overloading:
  1093.  * myString + yourString might concatenate two string objects
  1094.  * myDate++ might increment a Date object
  1095.  * a * b might multiply two Number objects
  1096.  * a[i] might access an element of an Array object
  1097.  * x = *p might dereference a "smart pointer" that actually "points" to a disk
  1098.    record -- it could actually seek to the location on disk where p "points"
  1099.    and return the appropriate record into x
  1100.  
  1101. ==============================================================================
  1102.  
  1103. [13.4] But operator overloading makes my class look ugly; isn't it supposed to
  1104.        make my code clearer?
  1105.  
  1106. Operator overloading makes life easier for the users of a class[13.2], not for
  1107. the developer of the class!
  1108.  
  1109. Consider the following example.
  1110.  
  1111.     class Array {
  1112.     public:
  1113.       int& operator[] (unsigned i);      // Some people don't like this syntax
  1114.       // ...
  1115.     };
  1116.  
  1117.     inline
  1118.     int& Array::operator[] (unsigned i)  // Some people don't like this syntax
  1119.     {
  1120.       // ...
  1121.     }
  1122.  
  1123. Some people don't like the keyword operator or the somewhat funny syntax that
  1124. goes with it in the body of the class itself.  But the operator overloading
  1125. syntax isn't supposed to make life easier for the developer of a class.  It's
  1126. supposed to make life easier for the users of the class:
  1127.  
  1128.     int main()
  1129.     {
  1130.       Array a;
  1131.       a[3] = 4;   // User code should be obvious and easy to understand...
  1132.     }
  1133.  
  1134. Remember: in a reuse-oriented world, there will usually be many people who use
  1135. your class, but there is only one person who builds it (yourself); therefore
  1136. you should do things that favor the many rather than the few.
  1137.  
  1138. ==============================================================================
  1139.  
  1140. [13.5] What operators can/cannot be overloaded? [UPDATED!]
  1141.  
  1142. [Recently got rid of #if/#else/#endif by splitting the example thanks to Stan
  1143. Brown (on 1/00).]
  1144.  
  1145. Most can be overloaded. The only C operators that can't be are . and ?: (and
  1146. sizeof, which is technically an operator).  C++ adds a few of its own
  1147. operators, most of which can be overloaded except :: and .*.
  1148.  
  1149. Here's an example of the subscript operator (it returns a reference).  First
  1150. without operator overloading:
  1151.  
  1152.     class Array {
  1153.     public:
  1154.       int& elem(unsigned i)        { if (i > 99) error(); return data[i]; }
  1155.     private:
  1156.       int data[100];
  1157.     };
  1158.  
  1159.     int main()
  1160.     {
  1161.       Array a;
  1162.       a.elem(10) = 42;
  1163.       a.elem(12) += a.elem(13);
  1164.     }
  1165.  
  1166. Now the same logic is presented with operator overloading:
  1167.  
  1168.     class Array {
  1169.     public:
  1170.       int& operator[] (unsigned i) { if (i > 99) error(); return data[i]; }
  1171.     private:
  1172.       int data[100];
  1173.     };
  1174.  
  1175.     int main()
  1176.     {
  1177.       Array a;
  1178.       a[10] = 42;
  1179.       a[12] += a[13];
  1180.     }
  1181.  
  1182. ==============================================================================
  1183.  
  1184. [13.6] Can I overload operator== so it lets me compare two char[] using a
  1185.        string comparison?
  1186.  
  1187. No: at least one operand of any overloaded operator must be of some
  1188. user-defined type (most of the time that means a class).
  1189.  
  1190. But even if C++ allowed you to do this, which it doesn't, you wouldn't want to
  1191. do it anyway since you really should be using a string-like class rather than
  1192. an array of char in the first place[17.3] since arrays are evil[21.5].
  1193.  
  1194. ==============================================================================
  1195.  
  1196. [13.7] Can I create a operator** for "to-the-power-of" operations?
  1197.  
  1198. Nope.
  1199.  
  1200. The names of, precedence of, associativity of, and arity of operators is fixed
  1201. by the language.  There is no operator** in C++, so you cannot create one for a
  1202. class type.
  1203.  
  1204. If you're in doubt, consider that x ** y is the same as x * (*y) (in other
  1205. words, the compiler assumes y is a pointer).  Besides, operator overloading is
  1206. just syntactic sugar for function calls.  Although this particular syntactic
  1207. sugar can be very sweet, it doesn't add anything fundamental.  I suggest you
  1208. overload pow(base,exponent) (a double precision version is in <math.h>).
  1209.  
  1210. By the way, operator^ can work for to-the-power-of, except it has the wrong
  1211. precedence and associativity.
  1212.  
  1213. ==============================================================================
  1214.  
  1215. [13.8] How do I create a subscript operator for a Matrix class?
  1216.  
  1217. Use operator() rather than operator[].
  1218.  
  1219. When you have multiple subscripts, the cleanest way to do it is with operator()
  1220. rather than with operator[].  The reason is that operator[] always takes
  1221. exactly one parameter, but operator() can take any number of parameters (in the
  1222. case of a rectangular matrix, two paramters are needed).
  1223.  
  1224. For example:
  1225.  
  1226.     class Matrix {
  1227.     public:
  1228.       Matrix(unsigned rows, unsigned cols);
  1229.       double& operator() (unsigned row, unsigned col);
  1230.       double  operator() (unsigned row, unsigned col) const;
  1231.       // ...
  1232.      ~Matrix();                              // Destructor
  1233.       Matrix(const Matrix& m);               // Copy constructor
  1234.       Matrix& operator= (const Matrix& m);   // Assignment operator
  1235.       // ...
  1236.     private:
  1237.       unsigned rows_, cols_;
  1238.       double* data_;
  1239.     };
  1240.  
  1241.     inline
  1242.     Matrix::Matrix(unsigned rows, unsigned cols)
  1243.       : rows_ (rows),
  1244.         cols_ (cols),
  1245.         data_ (new double[rows * cols])
  1246.     {
  1247.       if (rows == 0 || cols == 0)
  1248.         throw BadIndex("Matrix constructor has 0 size");
  1249.     }
  1250.  
  1251.     inline
  1252.     Matrix::~Matrix()
  1253.     {
  1254.       delete[] data_;
  1255.     }
  1256.  
  1257.     inline
  1258.     double& Matrix::operator() (unsigned row, unsigned col)
  1259.     {
  1260.       if (row >= rows_ || col >= cols_)
  1261.         throw BadIndex("Matrix subscript out of bounds");
  1262.       return data_[cols_*row + col];
  1263.     }
  1264.  
  1265.     inline
  1266.     double Matrix::operator() (unsigned row, unsigned col) const
  1267.     {
  1268.       if (row >= rows_ || col >= cols_)
  1269.         throw BadIndex("const Matrix subscript out of bounds");
  1270.       return data_[cols_*row + col];
  1271.     }
  1272.  
  1273. Then you can access an element of Matrix m using m(i,j) rather than m[i][j]:
  1274.  
  1275.     int main()
  1276.     {
  1277.       Matrix m(10,10);
  1278.       m(5,8) = 106.15;
  1279.       cout << m(5,8);
  1280.       // ...
  1281.     }
  1282.  
  1283. ==============================================================================
  1284.  
  1285. [13.9] Why shouldn't my Matrix class's interface look like an array-of-array?
  1286.  
  1287. Here's what this FAQ is really all about: Some people build a Matrix class that
  1288. has an operator[] that returns a reference to an Array object, and that Array
  1289. object has an operator[] that returns an element of the Matrix (e.g., a
  1290. reference to a double).  Thus they access elements of the matrix using syntax
  1291. like m[i][j] rather than syntax like m(i,j)[13.8].
  1292.  
  1293. The array-of-array solution obviously works, but it is less flexible than the
  1294. operator() approach[13.8].  Specifically, there are easy performance tuning
  1295. tricks that can be done with the operator() approach that are more difficult in
  1296. the [][] approach, and therefore the [][] approach is more likely to lead to
  1297. bad performance, at least in some cases.
  1298.  
  1299. For example, the easiest way to implement the [][] approach is to use a
  1300. physical layout of the matrix as a dense matrix that is stored in row-major
  1301. form (or is it column-major; I can't ever remember).  In contrast, the
  1302. operator() approach[13.8] totally hides the physical layout of the matrix, and
  1303. that can lead to better performance in some cases.
  1304.  
  1305. Put it this way: the operator() approach is never worse than, and sometimes
  1306. better than, the [][] approach.
  1307.  * The operator() approach is never worse because it is easy to implement the
  1308.    dense, row-major physical layout using the operator() approach, so when that
  1309.    configuration happens to be the optimal layout from a performance
  1310.    standpoint, the operator() approach is just as easy as the [][] approach
  1311.    (perhaps the operator() approach is a tiny bit easier, but I won't quibble
  1312.    over minor nits).
  1313.  * The operator() approach is sometimes better because whenever the optimal
  1314.    layout for a given application happens to be something other than dense,
  1315.    row-major, the implementation is often significantly easier using the
  1316.    operator() approach compared to the [][] approach.
  1317.  
  1318. As an example of when a physical layout makes a significant difference, a
  1319. recent project happened to access the matrix elements in columns (that is, the
  1320. algorithm accesses all the elements in one column, then the elements in
  1321. another, etc.), and if the physical layout is row-major, the accesses can
  1322. "stride the cache".  For example, if the rows happen to be almost as big as the
  1323. processor's cache size, the machine can end up with a "cache miss" for almost
  1324. every element access.  In this particular project, we got a 20% improvement in
  1325. performance by changing the mapping from the logical layout (row,column) to the
  1326. physical layout (column,row).
  1327.  
  1328. Of course there are many examples of this sort of thing from numerical methods,
  1329. and sparse matrices are a whole other dimension on this issue.  Since it is, in
  1330. general, easier to implement a sparse matrix or swap row/column ordering using
  1331. the operator() approach, the operator() approach loses nothing and may gain
  1332. something -- it has no down-side and a potential up-side.
  1333.  
  1334. Use the operator() approach[13.8].
  1335.  
  1336. ==============================================================================
  1337.  
  1338. [13.10] Should I design my classes from the outside (interfaces first) or from
  1339.         the inside (data first)? [UPDATED!]
  1340.  
  1341. [Recently added friend relationship between LinkedListIterator and LinkedList
  1342. thanks to M≤nica Garcφa Garcφa; reworded "In the case of OO software..."
  1343. sentence thanks to Fabrice Clerc (on 3/00).]
  1344.  
  1345. From the outside!
  1346.  
  1347. A good interface provides a simplified view that is expressed in the vocabulary
  1348. of a user[7.3].  In the case of OO software, the interface is normally the set
  1349. of public methods of either a single class or a tight group of classes[14.2].
  1350.  
  1351. First think about what the object logically represents, not how you intend to
  1352. physically build it.  For example, suppose you have a Stack class that will be
  1353. built by containing a LinkedList:
  1354.  
  1355.     class Stack {
  1356.     public:
  1357.       // ...
  1358.     private:
  1359.       LinkedList list_;
  1360.     };
  1361.  
  1362. Should the Stack have a get() method that returns the LinkedList? Or a set()
  1363. method that takes a LinkedList? Or a constructor that takes a LinkedList?
  1364. Obviously the answer is No, since you should design your interfaces from the
  1365. outside-in.  I.e., users of Stack objects don't care about LinkedLists; they
  1366. care about pushing and popping.
  1367.  
  1368. Now for another example that is a bit more subtle.  Suppose class LinkedList is
  1369. built using a linked list of Node objects, where each Node object has a pointer
  1370. to the next Node:
  1371.  
  1372.     class Node { /*...*/ };
  1373.  
  1374.     class LinkedList {
  1375.     public:
  1376.       // ...
  1377.     private:
  1378.       Node* first_;
  1379.     };
  1380.  
  1381. Should the LinkedList class have a get() method that will let users access the
  1382. first Node? Should the Node object have a get() method that will let users
  1383. follow that Node to the next Node in the chain? In other words, what should a
  1384. LinkedList look like from the outside? Is a LinkedList really a chain of Node
  1385. objects? Or is that just an implementation detail? And if it is just an
  1386. implementation detail, how will the LinkedList let users access each of the
  1387. elements in the LinkedList one at a time?
  1388.  
  1389. One man's answer: A LinkedList is not a chain of Nodes.  That may be how it is
  1390. built, but that is not what it is.  What it is is a sequence of elements.
  1391. Therefore the LinkedList abstraction should provide a "LinkedListIterator"
  1392. class as well, and that "LinkedListIterator" might have an operator++ to go to
  1393. the next element, and it might have a get()/set() pair to access its value
  1394. stored in the Node (the value in the Node element is solely the responsibility
  1395. of the LinkedList user, which is why there is a get()/set() pair that allows
  1396. the user to freely manipulate that value).
  1397.  
  1398. Starting from the user's perspective, we might want our LinkedList class to
  1399. support operations that look similar to accessing an array using pointer
  1400. arithmetic:
  1401.  
  1402.     void userCode(LinkedList& a)
  1403.     {
  1404.       for (LinkedListIterator p = a.begin(); p != a.end(); ++p)
  1405.         cout << *p << '\n';
  1406.     }
  1407.  
  1408. To implement this interface, LinkedList will need a begin() method and an end()
  1409. method.  These return a "LinkedListIterator" object.  The "LinkedListIterator"
  1410. will need a method to go forward, ++p; a method to access the current element,
  1411. *p; and a comparison operator, p != a.end().
  1412.  
  1413. The code follows.  The key insight is that the LinkedList class does not have
  1414. any methods that lets users access the Nodes.  Nodes are an implementation
  1415. technique that is completely buried.  The LinkedList class could have its
  1416. internals replaced with a doubly linked list, or even an array, and the only
  1417. difference would be some performance differences with the prepend(elem) and
  1418. append(elem) methods.
  1419.  
  1420.     #include <assert.h>   // Poor man's exception handling
  1421.  
  1422.     typedef  int  bool;   // Someday we won't have to do this
  1423.  
  1424.     class LinkedListIterator;
  1425.     class LinkedList;
  1426.  
  1427.     class Node {
  1428.       // No public members; this is a "private class"
  1429.       friend LinkedListIterator;   // A friend class[14]
  1430.       friend LinkedList;
  1431.       Node* next_;
  1432.       int elem_;
  1433.     };
  1434.  
  1435.     class LinkedListIterator {
  1436.     public:
  1437.       bool operator== (LinkedListIterator i) const;
  1438.       bool operator!= (LinkedListIterator i) const;
  1439.       void operator++ ();   // Go to the next element
  1440.       int& operator*  ();   // Access the current element
  1441.     private:
  1442.       LinkedListIterator(Node* p);
  1443.       Node* p_;
  1444.       friend LinkedList;  // so LinkedList can construct a LinkedListIterator
  1445.     };
  1446.  
  1447.     class LinkedList {
  1448.     public:
  1449.       void append(int elem);    // Adds elem after the end
  1450.       void prepend(int elem);   // Adds elem before the beginning
  1451.       // ...
  1452.       LinkedListIterator begin();
  1453.       LinkedListIterator end();
  1454.       // ...
  1455.     private:
  1456.       Node* first_;
  1457.     };
  1458.  
  1459. Here are the methods that are obviously inlinable (probably in the same header
  1460. file):
  1461.  
  1462.     inline bool LinkedListIterator::operator== (LinkedListIterator i) const
  1463.     {
  1464.       return p_ == i.p_;
  1465.     }
  1466.  
  1467.     inline bool LinkedListIterator::operator!= (LinkedListIterator i) const
  1468.     {
  1469.       return p_ != i.p_;
  1470.     }
  1471.  
  1472.     inline void LinkedListIterator::operator++()
  1473.     {
  1474.       assert(p_ != NULL);  // or if (p_==NULL) throw ...
  1475.       p_ = p_->next_;
  1476.     }
  1477.  
  1478.     inline int& LinkedListIterator::operator*()
  1479.     {
  1480.       assert(p_ != NULL);  // or if (p_==NULL) throw ...
  1481.       return p_->elem_;
  1482.     }
  1483.  
  1484.     inline LinkedListIterator::LinkedListIterator(Node* p)
  1485.       : p_(p)
  1486.     { }
  1487.  
  1488.     inline LinkedListIterator LinkedList::begin()
  1489.     {
  1490.       return first_;
  1491.     }
  1492.  
  1493.     inline LinkedListIterator LinkedList::end()
  1494.     {
  1495.       return NULL;
  1496.     }
  1497.  
  1498. Conclusion: The linked list had two different kinds of data.  The values of the
  1499. elements stored in the linked list are the responsibility of the user of the
  1500. linked list (and only the user; the linked list itself makes no attempt to
  1501. prohibit users from changing the third element to 5), and the linked list's
  1502. infrastructure data (next pointers, etc.), whose values are the responsibility
  1503. of the linked list (and only the linked list; e.g., the linked list does not
  1504. let users change (or even look at!) the various next pointers).
  1505.  
  1506. Thus the only get()/set() methods were to get and set the elements of the
  1507. linked list, but not the infrastructure of the linked list.  Since the linked
  1508. list hides the infrastructure pointers/etc., it is able to make very strong
  1509. promises regarding that infrastructure (e.g., if it was a doubly linked list,
  1510. it might guarantee that every forward pointer was matched by a backwards
  1511. pointer from the next Node).
  1512.  
  1513. So, we see here an example of where the values of some of a class's data is the
  1514. responsibility of users (in which case the class needs to have get()/set()
  1515. methods for that data) but the data that the class wants to control does not
  1516. necessarily have get()/set() methods.
  1517.  
  1518. Note: the purpose of this example is not to show you how to write a linked-list
  1519. class.  In fact you should not "roll your own" linked-list class since you
  1520. should use one of the "container classes" provided with your compiler.  Ideally
  1521. you'll use one of the standard container classes[32.1] such as the list<T>
  1522. template.
  1523.  
  1524. ==============================================================================
  1525.  
  1526. -- 
  1527. Marshall Cline / 972-931-9470 / mailto:cline@parashift.com
  1528.