Cplus Faq
Cplus Faq
Table of Contents:
[1] Copying permissions
[2] On-line sites that distribute this document
[3] C++-FAQ-Book versus C++-FAQ-Lite
[4] Recent changes to this document
[5] Netiquette when posting to comp.lang.c++
[6] Big Picture issues
[7] Classes and objects
[8] References
[9] Inline functions
[10] Constructors
[11] Destructors
[12] Assignment operators
[13] Operator overloading
[14] Friends
[15] Input/output via <iostream> and <cstdio>
[16] Freestore management
[17] Exceptions and error handling
[18] Const correctness
[19] Inheritance basics
[20] Inheritance virtual functions
[21] Inheritance proper inheritance and substitutability
[22] Inheritance abstract base classes (ABCs)
[17.1] What are some ways try / catch / throw can improve
software quality?
[Recently created (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
So compared to error reporting via return-codes and if, using try / catch / throw is likely to result
in code that has fewer bugs, is less expensive to develop, and has faster time-to-market. Of course if your
organization doesn't have any experiential knowledge of try / catch / throw, you might want to use
it on a toy project first just to make sure you know what you're doing you should always get used to a
weapon on the firing range before you bring it to the front lines of a shooting war.
[ Top | Bottom | Previous section | Next section ]
Throw an exception.
Constructors don't have a return type, so it's not possible to use return codes. The best way to signal
constructor failure is therefore to throw an exception.
If you don't have or won't use exceptions, here's a work-around. If a constructor fails, the constructor can
put the object into a "zombie" state. Do this by setting an internal status bit so the object acts sort of like
it's dead even though it is technically still alive. Then add a query ("inspector") member function to
check this "zombie" bit so users of your class can find out if their object is truly alive, or if it's a zombie
(i.e., a "living dead" object). Also you'll probably want to have your other member functions check this
zombie bit, and, if the object isn't really alive, do a no-op (or perhaps something more obnoxious such as
abort()). This is really ugly, but it's the best you can do if you can't (or don't want to) use exceptions.
[ Top | Bottom | Previous section | Next section ]
Write a message to a log-file. Or call Aunt Tilda. But do not throw an exception!
Here's why (buckle your seat-belts):
The C++ rule is that you must never throw an exception from a destructor that is being called during the
"stack unwinding" process of another exception. For example, if someone says throw Foo(), the
stack will be unwound so all the stack frames between the throw Foo() and the
} catch (Foo e) { will get popped. This is called stack unwinding.
During stack unwinding, all the local objects in all those stack frames are destructed. If one of those
destructors throws an exception (say it throws a Bar object), the C++ runtime system is in a no-win
situation: should it ignore the Bar and end up in the } catch (Foo e) { where it was originally
headed? Should it ignore the Foo and look for a } catch (Bar e) { handler? There is no good
answer -- either choice loses information.
So the C++ language guarantees that it will call terminate() at this point, and terminate() kills
[Recently rewrote the last half (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
If what you really want to do is work with strings, don't use an array of char in the first place, since
arrays are evil. Instead use an object of some string-like class.
For example, suppose you want to get a copy of a string, fiddle with the copy, then append another string
to the end of the fiddled copy. The array-of-char approach would look something like this:
void userCode(const char* s1, const char* s2)
{
// Make a copy of s1:
} catch (...) {
delete[] copy; // Prevent memory leaks if we got an exception
throw; // Re-throw the current exception
}
That's a total of two (2) lines of code within the body of the function, as compared with twelve (12) lines
of code in the previous example. Most of the savings came from memory management, but some also
came because we didn't have to explicitly call strxxx() routines. Here are some high points:
We do not need to explicitly write any code that reallocates memory when we grow the string,
since std::string handles memory management automatically.
We do not need to delete[] anything at the end, since std::string handles memory
management automatically.
We do not need a try block in this second example, since std::string handles memory
management automatically, even if someone somewhere throws an exception.
[ Top | Bottom | Previous section | Next section ]
void userCode(Fred& x)
{
x = x; // Self-assignment
}
Obviously no one ever explicitly does a self assignment like the above, but since more than one pointer
or reference can point to the same object (aliasing), it is possible to have self assignment without
knowing it:
#include "Fred.hpp" // Declares class Fred
int main()
{
Fred z;
userCode(z, z);
}
[ Top | Bottom | Previous section | Next section ]
class Fred {
public:
Fred() : p_(new Wilma()) { }
Fred(const Fred& f) : p_(new Wilma(*f.p_)) { }
~Fred() { delete p_; }
Fred& operator= (const Fred& f)
{
// Bad code: Doesn't handle self-assignment!
delete p_; // Line #1
p_ = new Wilma(*f.p_); // Line #2
return *this;
}
private:
Wilma* p_;
};
If someone assigns a Fred object to itself, line #1 deletes both this->p_ and f.p_ since *this and
f are the same object. But line #2 uses *f.p_, which is no longer a valid object. This will likely cause a
major disaster.
The bottom line is that you the author of class Fred are responsible to make sure self-assignment on a
Fred object is innocuous. Do not assume that users won't ever do that to your objects. It is your fault if
your object crashes when it gets a self-assignment.
Aside: the above Fred::operator= (const Fred&) has a second problem: If an exception is
thrown while evaluating new Wilma(*f.p_) (e.g., an out-of-memory exception or an exception in
Wilma's copy constructor), this->p_ will be a dangling pointer it will point to memory that is no
longer valid. This can be solved by allocating the new objects before deleting the old objects.
[Recently reworded the last paragraph (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
You should worry about self assignment every time you create a class. This does not mean that you need
to add extra code to all your classes: as long as your objects gracefully handle self assignment, it doesn't
matter whether you had to add extra code or not.
If you do need to add extra code to your assignment operator, here's a simple and effective technique:
Fred& Fred::operator= (const Fred& f)
{
if (this == &f) return *this; // Gracefully handle self assignment
return *this;
}
This explicit test isn't always necessary. For example, if you were to fix the assignment operator in the
previous FAQ to handle exceptions thrown by new and/or exceptions thrown by the copy constructor of
class Wilma, you might produce the following code. Note that this code has the (pleasant) side effect of
automatically handling self assignment as well:
Fred& Fred::operator= (const Fred& f)
{
// This code gracefully (albeit implicitly) handles self assignment
Wilma* tmp = new Wilma(*f.p_); // It would be OK if an exception got thrown here
delete p_;
p_ = tmp;
return *this;
}
In cases like the previous example (where self assignment is harmless but inefficient), some
programmers want to improve the efficiency of self assignment by adding an otherwise unnecessary test,
such as "if (this == &f) return *this;". It is generally the wrong tradeoff to make self
assignment more efficient by making the non-self assignment case less efficient. For example, adding the
above if test to the Fred assignment operator would make the non-self assignment case slightly less
efficient (an extra (and unnecessary) conditional branch). If self assignment actually occured once in a
thousand times, the if would waste cycles 99.9% of the time.
[ Top | Bottom | Previous section | Next section ]
Vehicle is the "superclass" of Car (this not as common in the C++ community)
(Note: this FAQ has to do with public inheritance; private and protected inheritance are
different.)
[ Top | Bottom | Previous section | Next section ]
A class has two distinct interfaces for two distinct sets of clients:
It has a public: interface that serves unrelated classes
Unless you expect all your derived classes to be built by your own team, you should consider making
your base class's bits be private:, and use protected: inline access functions by which derived
classes will access the private data in the base class. This way the private bits can change, but the
derived class's code won't break unless you change the protected access functions.
[ Top | Bottom | Previous section | Next section ]
In the world of industrial software, C++ is viewed as a solid, mature, mainstream tool. It has widespread
industry support which makes it "good" from an overall business perspective.
[ Top | Bottom | Previous section | Next section ]
[6.4] Is C++ better than Ada? (or Visual Basic, C, FORTRAN, Pascal,
Smalltalk, or any other language?)
This question generates much much more heat than light. Please read the following before posting some
variant of this question.
In 99% of the cases, programming language selection is dominated by business considerations, not by
technical considerations. Things that really end up mattering are things like availability of a
programming environment for the development machine, availability of runtime environment(s) for the
deployment machine(s), licensing/legal issues of the runtime and/or development environments,
availability of trained developers, availability of consulting services, and corporate culture/politics. These
business considerations generally play a much greater role than compile time performance, runtime
performance, static vs. dynamic typing, static vs. dynamic binding, etc.
Anyone who argues in favor of one language over another in a purely technical manner (i.e., who ignores
the dominant business issues) exposes themself as a techie weenie, and deserves not to be heard.
[ Top | Bottom | Previous section | Next section ]
Get your people two books: one to tell them what is legal, another to tell them what is moral
You should not bother having your people trained in Smalltalk as a stepping-stone to learning
OO/C++
C++ lets developers provide simplified interfaces to software chunks, which improves the
defect-rate when those chunks are (re)used
C++ lets you exploit developer's intuition through operator overloading, which reduces the
learning curve for (re)users
C++ localizes access to a software chunk, which reduces the cost of changes.
C++ reduces the safety-vs.-usability tradeoff, which improves the cost of (re)using a chunk of
software.
C++ reduces the safety-vs.-speed tradeoff, which improves defect rates without degrading
performance.
C++ gives you inheritance and dynamic binding which let old code call new code, making it
possible to quickly extend/adapt your software to hit narrow market windows.
[ Top | Bottom | Previous section | Next section ]
[Recently inserted "the" before "difference" thanks to Stan Brown and reworded references to STL (on 7/00). Click here to
go to the next FAQ in the "chain" of recent changes.]
Yes!
Without virtual functions, C++ wouldn't be object-oriented. Operator overloading and non-virtual
member functions are great, but they are, after all, just syntactic sugar for the more typical C notion of
passing a pointer to a struct to a function. The standard library contains numerous templates that
illustrate "generic programming" techniques, which are also great, but virtual functions are still at the
heart of object-oriented programming using C++.
From a business perspective, there is very little reason to switch from straight C to C++ without
virtual functions (we'll ignore generic programming and the standard library in this FAQ). Technical
people often think that there is a large difference between C and non-OO C++, but without OO, the
difference usually isn't enough to justify the cost of training developers, new tools, etc. In other words, if
I were to advise a manager regarding whether to switch from C to non-OO C++ (i.e., to switch languages
but not paradigms), I'd probably discourage him or her unless there were compelling tool-oriented
reasons. From a business perspective, OO can help make systems extensible and adaptable, but just the
syntax of C++ classes without OO may not even reduce the maintenance cost, and it surely adds to the
training cost significantly.
Bottom line: C++ without virtual is not OO. Programming with classes but without dynamic binding
is called "object based," but not "object oriented." Throwing out virtual functions is the same as
throwing out OO. All you have left is object-based programming, similar to the original Ada language
(the new Ada language, by the way, supports true OO rather than just object-based programming).
[ Top | Bottom | Previous section | Next section ]
[6.9] I'm from Missouri. Can you give me a simple reason why
virtual functions (dynamic binding) make a big difference?
Overview: Dynamic binding can improve reuse by letting old code call new code.
Before OO came along, reuse was accomplished by having new code call old code. For example, a
programmer might write some code that called some reusable code such as printf().
With OO, reuse can also be accomplished by having old code call new code. For example, a programmer
might write some code that is called by a framework that was written by their great, great grandfather.
There's no need to change great-great-grandpa's code. In fact, it doesn't even need to be recompiled. Even
if all you have left is the object file and the source code that great-great-grandpa wrote was lost 25 years
ago, that ancient object file will call the new extension without anything falling apart.
That is extensibility, and that is OO.
[ Top | Bottom | Previous section | Next section ]
Yes.
The C++ standard was finalized and adopted by ISO (International Organization for Standardization) as
well as several national standards organizations such as ANSI (The American National Standards
Institute), BSI (The British Standards Institute), DIN (The German National Standards Organization).
The ISO standard was finalized and adopted by unanimous vote November 14, 1997.
The ANSI C++ committee is called "X3J16". The ISO C++ standards group is called "WG21". The
major players in the ANSI/ISO C++ standards process include just about everyone: representatives from
Australia, Canada, Denmark, France, Germany, Ireland, Japan, the Netherlands, New Zealand, Sweden,
the UK, and the USA, along with representatives from about a hundred companies and many interested
individuals. Major players include AT&T, Ericsson, Digital, Borland, Hewlett Packard, IBM, Mentor
Graphics, Microsoft, Silicon Graphics, Sun Microsystems, and Siemens. After about 8 years of work, this
standard is now complete. On November 14, 1997, the standard was approved by a unanimous vote of
the countries that had representatives present in Morristown.
[ Top | Bottom | Previous section | Next section ]
Note: The ISO document is well over ten times more expensive than the ANSI document, however the
technical content is the same. The ISO document has a different title page, but the technical material is
identical to the ANSI document. Please don't email asking me why ISO charges so much more for
fundamentally the same thing; that's ISO's business decision; you'll have to take it up with ISO's
publishing/sales department.
There are at least two ways to get a hard-copy of this document:
$175 [published by ANSI]: go to this page, select "Hardcopy" from the pull-down, and click
"Place this in your shopping basket."
Unknown price [published by ANSI]: call NCITS (National Committee for Information
Technology Standards; this is the new name of the organization that used to be called "X3"). The
contact person is Monica Vega, 202-626-5739 or 202-626-5738. Ask for document FDC 14882.
Be prepared to spend some money the document is certainly not free.
There are two other potentially interesting (and free) documents you might want to look at:
$0: If you're willing to put up with a (free) document that's non-authorative, out-of-date, and
partially incorrect, you can get "committee draft #2" here and/or here.
$0: The ISO committee's press release (not a copy of the ANSI or ISO standards!) is here. This
press release is readable by non-programmers.
[ Top | Bottom | Previous section | Next section ]
[ C++ FAQ Lite | Table of contents | Subject index | About the author | | Download your own copy ]
Revised Apr 8, 2001
means "an instance of a class." Thus a class defines the behavior of possibly many objects (instances).
[ Top | Bottom | Previous section | Next section ]
The "volatile parts" are the implementation details. If the chunk is a single class, the volatile part is
normally encapsulated using the private: and/or protected: keywords. If the chunk is a tight
group of classes, encapsulation can be used to deny access to entire classes in that group. Inheritance can
also be used as a form of encapsulation.
The "stable parts" are the interfaces. A good interface provides a simplified view in the vocabulary of a
user, and is designed from the outside-in (here a "user" means another developer, not the end-user who
buys the completed application). If the chunk is a single class, the interface is simply the class's
public: member functions and friend functions. If the chunk is a tight group of classes, the
interface can include several of the classes in the chunk.
Designing a clean interface and separating that interface from its implementation merely allows users to
use the interface. But encapsulating (putting "in a capsule") the implementation forces users to use the
interface.
[ Top | Bottom | Previous section | Next section ]
[7.5] How does C++ help with the tradeoff of safety vs. usability?
In C, encapsulation was accomplished by making things static in a compilation unit or module. This
prevented another module from accessing the static stuff. (By the way, that use is now deprecated:
don't do that in C++.)
Unfortunately this approach doesn't support multiple instances of the data, since there is no direct support
for making multiple instances of a module's static data. If multiple instances were needed in C,
programmers typically used a struct. But unfortunately C structs don't support encapsulation. This
exacerbates the tradeoff between safety (information hiding) and usability (multiple instances).
In C++, you can have both multiple instances and encapsulation via a class. The public: part of a class
contains the class's interface, which normally consists of the class's public: member functions and its
friend functions. The private: and/or protected: parts of a class contain the class's
implementation, which is typically where the data lives.
The end result is like an "encapsulated struct." This reduces the tradeoff between safety (information
hiding) and usability (multiple instances).
[ Top | Bottom | Previous section | Next section ]
STL ("Standard Templates Library") is a library that consists mainly of (very efficient) container classes,
along with some iterators and algorithms to work with the contents of these containers.
Technically speaking the term "STL" is no longer meaningful since the classes provided by the STL have
been fully integrated into the standard library, along with other standard classes like std::ostream,
etc. Nonetheless many people still refer to the STL as if it was a separate thing, so you might as well get
used to hearing that term.
[ Top | Bottom | Previous section | Next section ]
Since the classes that were part of the STL have become part of the standard library, your compiler
should provide these classes. If your compiler doesn't include these standard classes, either get an
updated version of your compiler or download a copy of the STL classes from one of the following:
An STL site: ftp://ftp.cs.rpi.edu/pub/stl
STL functions such as std::find_if() help you find a T element in a container of T's. But if you
have a container of pointers such as std::vector<Fred*>, these functions will enable you to find
an element that matches a given Fred* pointer, but they don't let you find an element that matches a
given Fred object.
The solution is to use an optional parameter that specifies the "match" function. The following class
template lets you compare the objects on the other end of the dereferenced pointers.
template<class T>
class DereferencedEqual {
public:
DereferencedEqual(const T* p) : p_(p) { }
bool operator() (const T* p2) const { return *p_ == *p2; }
private:
const T* p_;
};
Now you can use this template to find an appropriate Fred object:
void userCode(std::vector<Fred*> v, const Fred& match)
{
std::find_if(v.begin(), v.end(), DereferencedEqual<Fred>(&match));
// ...
}
[32.5] How can you tell if you have a dynamically typed C++ class
library?
Hint #1: when everything is derived from a single root class, usually Object.
Hint #2: when the container classes (List, Stack, Set, etc) are non-templates.
Hint #3: when the container classes (List, Stack, Set, etc) insert/extract elements as pointers
to Object. This lets you put an Apple into such a container, but when you get it out, the
compiler knows only that it is derived from Object, so you have to use a pointer cast to convert
it back to an Apple*; and you better pray a lot that it really is an Apple, cause your blood is on
your own head).
You can make the pointer cast "safe" by using dynamic_cast, but this dynamic testing is just that:
dynamic. This coding style is the essence of dynamic typing in C++. You call a function that says
"convert this Object into an Apple or give me NULL if its not an Apple," and you've got dynamic
typing: you don't know what will happen until run-time.
When you use templates to implement your containers, the C++ compiler can statically validate 90+% of
an application's typing information (the figure "90+%" is apocryphal; some claim they always get 100%,
those who need persistence get something less than 100% static type checking). The point is: C++ gets
genericity from templates, not from inheritance.
[ Top | Bottom | Previous section | Next section ]
of the Smalltalk class library. There are some ways where NIHCL's use of dynamic typing helps (e.g.,
persistent objects). There are also places where its use of dynamic typing creates tension with the static
typing of the C++ language.
[ Top | Bottom | Previous section | Next section ]
[32.9] Where can I get tons and tons of more information on C++
class libraries?
The C++ Libraries FAQ is maintained by Nikki Locke and is available at
www.trumphurst.com/cpplibs1.html
[ Top | Bottom | Previous section | Next section ]
Thank you for reading this answer rather than just trying to set your own coding standards.
But beware that some people on comp.lang.c++ are very sensitive on this issue. Nearly every software engineer has, at some point, been
exploited by someone who used coding standards as a "power play." Furthermore some attempts to set C++ coding standards have been made by
those who didn't know what they were talking about, so the standards end up being based on what was the state-of-the-art when the standards
setters were writing code. Such impositions generate an attitude of mistrust for coding standards.
Obviously anyone who asks this question wants to be trained so they don't run off on their own ignorance, but nonetheless posting a question such
as this one to comp.lang.c++ tends to generate more heat than light.
[ Top | Bottom | Previous section | Next section ]
[25.3] Should our organization determine coding standards from our C experience?
No!
No matter how vast your C experience, no matter how advanced your C expertise, being a good C programmer does not make you a good C++
programmer. Converting from C to C++ is more than just learning the syntax and semantics of the ++ part of C++. Organizations who want the
promise of OO, but who fail to put the "OO" into "OO programming", are fooling themselves; the balance sheet will show their folly.
C++ coding standards should be tempered by C++ experts. Asking comp.lang.c++ is a start. Seek out experts who can help guide you away
from pitfalls. Get training. Buy libraries and see if "good" libraries pass your coding standards. Do not set standards by yourself unless you have
considerable experience in C++. Having no standard is better than having a bad standard, since improper "official" positions "harden" bad brain
traces. There is a thriving market for both C++ training and libraries from which to pull expertise.
One more thing: whenever something is in demand, the potential for charlatans increases. Look before you leap. Also ask for student-reviews from
past companies, since not even expertise makes someone a good communicator. Finally, select a practitioner who can teach, not a full time teacher
who has a passing knowledge of the language/paradigm.
[ Top | Bottom | Previous section | Next section ]
The headers in ISO Standard C++ don't have a .h suffix. This is something the standards committee changed from former practice. The details are
different between headers that existed in C and those that are specific to C++.
The C++ standard library is guaranteed to have 18 standard headers from the C language. These headers come in two standard flavors, <cxxx>
and <xxx.h> (where xxx is the basename of the header, such as stdio, stdlib, etc). These two flavors are identical except the <cxxx>
versions provide their declarations in the std namespace only, and the <xxx.h> versions make them available both in std namespace and in the
global namespace. The committee did it this way so that existing C code could continue to be compiled in C++. However the <xxx.h> versions
are deprecated, meaning they are standard now but might not be part of the standard in future revisions. (See clause D.5 of the ISO C++ standard.)
The C++ standard library is also guaranteed to have 32 additional standard headers that have no direct counterparts in C, such as <iostream>,
<string>, and <new>. You may see things like #include <iostream.h> and so on in old code, and some compiler vendors offer .h
versions for that reason. But be careful: the .h versions, if available, may differ from the standard versions. And if you compile some units of a
program with, for example, <iostream> and others with <iostream.h>, the program may not work.
For new projects, use only the <xxx> headers, not the <xxx.h> headers.
When modifying or extending existing code that uses the old header names, you should probably follow the practice in that code unless there's
some important reason to switch to the standard headers (such as a facility available in standard <iostream> that was not available in the
vendor's <iostream.h>). If you need to standardize existing code, make sure to change all C++ headers in all program units including external
libraries that get linked in to the final executable.
All of this affects the standard headers only. You're free to name your own headers anything you like; see [25.8].
[ Top | Bottom | Previous section | Next section ]
[25.5] Is the ?: operator evil since it can be used to create unreadable code?
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
No, but as always, remember that readability is one of the most important things.
Some people feel the ?: ternary operator should be avoided because they find it confusing at times compared to the good old if statement. In
many cases ?: tends to make your code more difficult to read (and therefore you should replace those usages of ?: with if statements), but there
are times when the ?: operator is clearer since it can emphasize what's really happening, rather than the fact that there's an if in there somewhere.
Let's start with a really simple case. Suppose you need to print the result of a function call. In that case you should put the real goal (printing) at the
beginning of the line, and bury the function call within the line since it's relatively incidental (this left-right thing is based on the intuitive notion
that most developers think the first thing on a line is the most important thing):
// Preferred (emphasizes the major goal printing):
std::cout << funct();
Yes, there are some practices which are generally considered dangerous. However none of these are universally "bad," since situations arise when
even the worst of these is needed:
A class Fred's assignment operator should return *this as a Fred& (allows chaining of assignments)
A class with any of {destructor, assignment operator, copy constructor} generally needs all 3
A class Fred's copy constructor and assignment operator should have const in the parameter: respectively
Fred::Fred(const Fred&) and Fred& Fred::operator= (const Fred&)
When initializing an object's member objects in the constructor, always use initialization lists rather than assignment. The performance
difference for user-defined classes can be substantial (3x!)
Assignment operators should make sure that self assignment does nothing, otherwise you may have a disaster. In some cases, this may
require you to add an explicit test to your assignment operators.
In classes that define both += and +, a += b and a = a + b should generally do the same thing; ditto for the other identities of
built-in/intrinsic types (e.g., a += 1 and ++a; p[i] and *(p+i); etc). This can be enforced by writing the binary operations using the
op= forms. E.g.,
Fred operator+ (const Fred& a, const Fred& b)
{
Fred ans = a;
ans += b;
return ans;
}
This way the "constructive" binary operators don't even need to be friends. But it is sometimes possible to more efficiently implement
common operations (e.g., if class Fred is actually std::string, and += has to reallocate/copy string memory, it may be better to
know the eventual length from the beginning).
[ Top | Bottom | Previous section | Next section ]
It's a precedent thing. If you have a Pascal or Smalltalk background, youProbablySquashNamesTogether like this. If you have an Ada
background, You_Probably_Use_A_Large_Number_Of_Underscores like this. If you have a Microsoft Windows background, you
probably prefer the "Hungarian" style which means you jkuidsPrefix vndskaIdentifiers ncqWith ksldjfTheir nmdsadType.
And then there are the folks with a Unix C background, who abbr evthng n use vry srt idntfr nms. (AND THE FORTRN PRGMRS
LIMIT EVRYTH TO SIX LETTRS.)
So there is no universal standard. If your project team has a particular coding standard for identifier names, use it. But starting another Jihad over
this will create a lot more heat than light. From a business perspective, there are only two things that matter: The code should be generally
www.cs.princeton.edu/~dwallach/CPlusPlusStyle.html
cpptips.hyperformix.com/conventions/cppconventions_1.html
www.oma.com/ottinger/Naming.html
v2ma09.gsfc.nasa.gov/coding_standards.html
fndaub.fnal.gov:8000/standards/standards.html
www.arcticlabs.com/codingstandards/
cliffie.nosc.mil/~NAPDOC/docprj/cppcodingstd/
www.possibility.com/cpp/
groucho.gsfc.nasa.gov/Code_520/Code_522/Projects/DRSL/documents/templates/cpp_style_guide.html
www.wildfire.com/~ag/Engineering/Development/C++Style/
The Ellemtel coding guidelines are available at
www.cs.umd.edu/users/cml/cstyle/Ellemtel-rules.html
www.doc.ic.ac.uk/lab/cplus/c++.rules/
www.mgl.co.uk/people/kirit/cpprules.html
Note: I do NOT warrant or endorse these URLs and/or their contents. They are listed as a public service only. I haven't checked their details, so I
don't know if they'll help you or hurt you. Caveat emptor.
[ Top | Bottom | Previous section | Next section ]
[33.2] Where can I get more information on using MFC and Visual C++?
The MFC/Visual C++ FAQ (mfcfaq.stingray.com/) is maintained by Michael Pickens (formerly maintained by
Scot Wingo). Another FAQ is available at www.mvps.org/vcfaq.
[ Top | Bottom | Previous section | Next section ]
(CStatusBar*)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
p->SetPaneText(1, s);
This works with MFC v.1.00 which hopefully means it will work with other versions as well.
[ Top | Bottom | Previous section | Next section ]
[33.4] How can I decompile an executable program back into C++ source
code?
You gotta be kidding, right?
Here are a few of the many reasons this is not even remotely feasible:
What makes you think the program was written in C++ to begin with?
Even if you are sure it was originally written (at least partially) in C++, which one of the gazillion C++
compilers produced it?
Even if you know the compiler, which particular version of the compiler was used?
Even if you know the compiler's manufacturer and version number, what compile-time options were used?
Even if you know the compiler's manufacturer and version number and compile-time options, what third party
libraries were linked-in, and what was their version?
Even if you know all that stuff, most executables have had their debugging information stripped out, so the
resulting decompiled code will be totally unreadable.
Even if you know everything about the compiler, manufacturer, version number, compile-time options, third
party libraries, and debugging information, the cost of writing a decompiler that works with even one particular
compiler and has even a modest success rate at generating code would be a monumental effort on the par with
writing the compiler itself from scratch.
But the biggest question is not how you can decompile someone's code, but why do you want to do this? If you're trying
to reverse-engineer someone else's code, shame on you; go find honest work. If you're trying to recover from losing
your own source, the best suggestion I have is to make better backups next time.
[ Top | Bottom | Previous section | Next section ]
[33.5] Where can I get information about the C++ compiler from {Borland, IBM,
Microsoft, Symantec, Sun, etc.}?
[Recently updated the URL for IBM VisualAge C++ thanks to Rick Alther; updated the URL for GNU C++ thanks to Martin Honnen (on
7/00) and fixed "Semantic" to "Symantec" and "Gary Comeau" to "Greg Comeau" thanks to Scott Tringali; fixed the URL to SGI's
compiler thanks to Toon Knapen (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
If the compiler uses the "over-allocation" technique, the code for p = new Fred[n] looks something like the
following. Note that WORDSIZE is an imaginary machine-dependent constant that is at least sizeof(size_t),
possibly rounded up for any alignment constraints. On many machines, this constant will have a value of 4 or 8. It is
not a real C++ identifier that will be defined for your compiler.
// Original code: Fred* p = new Fred[n];
char* tmp = (char*) operator new[] (WORDSIZE + n * sizeof(Fred));
Fred* p = (Fred*) (tmp + WORDSIZE);
*(size_t*)tmp = n;
size_t i;
try {
for (i = 0; i < n; ++i)
new(p + i) Fred(); // Placement new
} catch (...) {
while (i-- != 0)
(p + i)->~Fred(); // Explicit call to the destructor
operator delete[] ((char*)p - WORDSIZE);
throw;
}
Then the delete[] p statement becomes:
// Original code: delete[] p;
size_t n = * (size_t*) ((char*)p - WORDSIZE);
while (n-- != 0)
(p + n)->~Fred();
If the compiler uses the associative array technique, the code for p = new Fred[n] looks something like this
(where arrayLengthAssociation is the imaginary name of a hidden, global associative array that maps from
void* to "size_t"):
// Original code: Fred* p = new Fred[n];
Fred* p = (Fred*) operator new[] (n * sizeof(Fred));
size_t i;
try {
for (i = 0; i < n; ++i)
new(p + i) Fred(); // Placement new
} catch (...) {
while (i-- != 0)
(p + i)->~Fred(); // Explicit call to the destructor
operator delete[] (p);
throw;
}
arrayLengthAssociation.insert(p, n);
Then the delete[] p statement becomes:
// Original code: delete[] p;
size_t n = arrayLengthAssociation.lookup(p);
while (n-- != 0)
(p + n)->~Fred();
operator delete[] (p);
Cfront uses this technique (it uses an AVL tree to implement the associative array).
Compared to the over-allocation technique, the associative array technique is slower, but less sensitive to the problem
of programmers saying delete p rather than delete[] p. For example, if you make a programming error by
saying delete p where you should have said delete[] p, only the first Fred in the array gets destructed, but the
heap may survive (unless you've replaced operator delete[] with something that doesn't simply call
operator delete, or unless the destructors for the other Fred objects were necessary).
[ Top | Bottom | Previous section | Next section ]
[33.8] If name mangling was standardized, could I link code compiled with
compilers from different compiler vendors?
Short answer: Probably not.
In other words, some people would like to see name mangling standards incorporated into the proposed C++ ANSI
standards in an attempt to avoiding having to purchase different versions of class libraries for different compiler
vendors. However name mangling differences are one of the smallest differences between implementations, even on
the same platform.
Here is a partial list of other differences:
Number and type of hidden arguments to member functions.
[33.9] GNU C++ (g++) produces big executables for tiny programs; Why?
libg++ (the library used by g++) was probably compiled with debug info (-g). On some machines, recompiling libg++
without debugging can save lots of disk space (approximately 1 MB; the down-side: you'll be unable to trace into
libg++ calls). Merely strip-ping the executable doesn't reclaim as much as recompiling without -g followed by
subsequent strip-ping the resultant a.out's.
Use size a.out to see how big the program code and data segments really are, rather than ls -s a.out which
includes the symbol table.
[ Top | Bottom | Previous section | Next section ]
The primary yacc grammar you'll want is from Ed Willink. Ed believes his grammar is fully compliant with the
ISO/ANSI C++ standard, however he doesn't warrant it: "the grammar has not," he says, "been used in anger." You can
get the grammar without action routines or the grammar with dummy action routines. You can also get the
corresponding lexer. For those who are interested in how he achieves a context-free parser (by pushing all the
ambiguities plus a small number of repairs to be done later after parsing is complete), you might want to read chapter 4
of his thesis.
There is also a very old yacc grammar that doesn't support templates, exceptions, nor namespaces; plus it deviates
from the core language in some subtle ways. You can get that grammar here or here.
[ Top | Bottom | Previous section | Next section ]
A good thing. It means using the keyword const to prevent const objects from getting mutated.
For example, if you wanted to create a function f() that accepted a std::string, plus you want to
promise callers not to change the caller's std::string that gets passed to f(), you can have f()
receive its std::string parameter...
void f1(const std::string& s); // Pass by reference-to-const
void f2(const std::string* sptr); // Pass by pointer-to-const
void f3(std::string s); // Pass by value
In the pass by reference-to-const and pass by pointer-to-const cases, any attempts to change to the
caller's std::string within the f() functions would be flagged by the compiler as an error at
compile-time. This check is done entirely at compile-time: there is no run-time space or speed cost for the
const. In the pass by value case (f3()), the called function gets a copy of the caller's std::string.
This means that f3() can change its local copy, but the copy is destroyed when f3() returns. In
particular f3() cannot change the caller's std::string object.
As an opposite example, if you wanted to create a function g() that accepted a std::string, but you
want to let callers know that g() might change the caller's std::string object. In this case you can
have g() receive its std::string parameter...
void g1(std::string& s); // Pass by reference-to-non-const
void g2(std::string* sptr); // Pass by pointer-to-non-const
The lack of const in these functions tells the compiler that they are allowed to (but are not required to)
change the caller's std::string object. Thus they can pass their std::string to any of the f()
functions, but only f3() (the one that receives its parameter "by value") can pass its std::string to
g1() or g2(). If f1() or f2() need to call either g() function, a local copy of the std::string
object must be passed to the g() function; the parameter to f1() or f2() cannot be directly passed to
either g() function. E.g.,
void g1(std::string& s);
std::string localCopy = s;
g1(localCopy); // OK since localCopy is not const
}
Naturally in the above case, any changes that g1() makes are made to the localCopy object that is local
to f1(). In particular, no changes will be made to the const parameter that was passed by reference to
f1().
[ Top | Bottom | Previous section | Next section ]
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the
"chain" of recent changes.]
Declaring the const-ness of a parameter is just another form of type safety. It is almost as if a const
std::string, for example, is a different class than an ordinary std::string, since the const
variant is missing the various mutative operations in the non-const variant (e.g., you can imagine that a
const std::string simply doesn't have an assignment operator).
If you find ordinary type safety helps you get systems correct (it does; especially in large systems), you'll
error (the error is caught by the compiler; no run-time tests are done, which means const doesn't slow
your program down).
[ Top | Bottom | Previous section | Next section ]
In other words, "Fred& const x" is functionally equivalent to "Fred& x". Since you're gaining
nothing by adding the const after the &, you shouldn't add it since it will confuse people. I.e., the const
will make some people think that the Fred is const, as if you had said "const Fred& x".
[ Top | Bottom | Previous section | Next section ]
The problem with using "Fred const& x" (with the const before the &) is that it could easily be
mis-typed as the nonsensical "Fred &const x" (with the const after the &).
[18.12] Why does the compiler allow me to change an int after I've
pointed at it with a const int*?
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the
"chain" of recent changes.]
Because "const int* p" means "p promises not to change the *p," not "*p promises not to change."
Causing a const int* to point to an int doesn't const-ify the int. The int can't be changed via the
const int*, but if someone else has an int* (note: no const) that points to ("aliases") the same int,
then that int* can be used to change the int. For example:
void f(const int* p1, int* p2)
{
int i = *p1; // Get the (original) value of *p1
*p2 = 7; // If p1 == p2, this will also change *p1
int main()
{
int x;
f(&x, &x); // This is perfectly legal (and even moral!)
}
Note that main() and f(const int*,int*) could be in different compilation units that are compiled
on different days of the week. In that case there is no way the compiler can possibly detect the aliasing at
compile time. Therefore there is no way we could make a language rule that prohibits this sort of thing. In
fact, we wouldn't even want to make such a rule, since in general it's considered a feature that you can have
many pointers pointing to the same thing. The fact that one of those pointers promises not to change the
underlying "thing" is just a promise made by the pointer; it's not a promise made by the "thing".
[ Top | Bottom | Previous section | Next section ]
"const Fred* p" means that the Fred can't be changed via pointer p, but there might be other ways to
get at the object without going through a const (such as an aliased non-const pointer such as a Fred*).
For example, if you have two pointers "const Fred* p" and "Fred* q" that point to the same Fred
object (aliasing), pointer q can be used to change the Fred object but pointer p cannot.
class Fred {
public:
void inspect() const; // A const member function
void mutate(); // A non-const member function
};
int main()
{
Fred f;
const Fred* p = &f;
Fred* q = &f;
[31.1] Why should I use container classes rather than simple arrays?
[Recently created with help from Stan Brown (on 7/00) and clarified "local" vs. "non-static local" thanks to Garen Parham
(on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
A std::vector is the most array-like of the standard container classes, but it also offers
various extra features such as bounds checking via the at() member function,
insertions/removals of elements, automatic memory management even if someone throws an
exception, ability to be passed both by reference and by value, etc.
A std::string is almost always better than an array of char (you can think of a
std::string as a "container class" for the sake of this discussion).
2. Container classes aren't best for everything, and sometimes you may need to use arrays. But that should
be very rare, and if/when it happens:
Please design your container class's public interface in such a way that the code that uses the
container class is unaware of the fact that there is an array inside.
The goal is to "bury" the array inside a container class. In other words, make sure there is a very
small number of lines of code that directly touch the array (just your own methods of your
container class) so everyone else (the users of your container class) can write code that doesn't
depend on there being an array inside your container class.
To net this out, arrays really are evil. You may not think so if you're new to C++. But after you write a big pile
of code that uses arrays (especially if you make your code leak-proof and exception-safe), you'll learn the
hard way. Or you'll learn the easy way by believing those who've already done things like that. The choice is
yours.
[ Top | Bottom | Previous section | Next section ]
int main()
{
// age is a map from string to int
std::map<std::string, int, std::less<std::string> > age;
std::cout << "Fred is " << age["Fred"] << " years old\n";
}
[ Top | Bottom | Previous section | Next section ]
The most important thing to remember is this: don't roll your own from scratch unless there is a compelling
reason to do so. In other words, instead of creating your own list or hashtable, use one of the standard class
templates such as std::vector<T> or std::list<T> or whatever.
Assuming you have a compelling reason to build your own container, here's how to handle inserting (or
accessing, changing, etc.) the elements.
To make the discussion concrete, I'll discuss how to insert an element into a linked list. This example is just
complex enough that it generalizes pretty well to things like vectors, hash tables, binary trees, etc.
A linked list makes it easy insert an element before the first or after the last element of the list, but limiting
ourselves to these would produce a library that is too weak (a weak library is almost worse than no library).
This answer will be a lot to swallow for novice C++'ers, so I'll give a couple of options. The first option is
easiest; the second and third are better.
1. Empower the List with a "current location," and member functions such as advance(),
backup(), atEnd(), atBegin(), getCurrElem(), setCurrElem(Elem),
insertElem(Elem), and removeElem(). Although this works in small examples, the notion of a
current position makes it difficult to access elements at two or more positions within the list (e.g., "for
all pairs x,y do the following...").
2. Remove the above member functions from List itself, and move them to a separate class,
ListPosition. ListPosition would act as a "current position" within a list. This allows
multiple positions within the same list. ListPosition would be a friend of class List, so
List can hide its innards from the outside world (else the innards of List would have to be
publicized via public member functions in List). Note: ListPosition can use operator
overloading for things like advance() and backup(), since operator overloading is syntactic
sugar for normal member functions.
3. Consider the entire iteration as an atomic event, and create a class template that embodies this event.
This enhances performance by allowing the public access member functions (which may be virtual
functions) to be avoided during the access, and this access often occurs within an inner loop.
Unfortunately the class template will increase the size of your object code, since templates gain speed
by duplicating code. For more, see [Koenig, "Templates as interfaces," JOOP, 4, 5 (Sept 91)], and
[Stroustrup, "The C++ Programming Language Third Edition," under "Comparator"].
[ Top | Bottom | Previous section | Next section ]
When you call a function template, the compiler tries to deduce the template type. Most of the time it can do
that successfully, but every once in a while you may want to help the compiler deduce the right type either
because it cannot deduce the type at all, or perhaps because it would deduce the wrong type.
For example, you might be calling a function template that doesn't have any parameters of its template
argument types, or you might want to force the compiler to do certain promotions on the arguments before
selecting the correct function template. In these cases you'll need to explicitly tell the compiler which
instantiation of the function template should be called.
Here is a sample function template where the template parameter T does not appear in the function's parameter
list. In this case the compiler cannot deduce the template parameter types when the function is called.
template<class T>
void f()
{
// ...
}
To call this function with T being an int or a std::string, you could say:
#include <string>
void sample()
{
f<int>(); // type T will be int in this call
f<std::string>(); // type T will be std::string in this call
}
Here is another function whose template parameters appear in the function's list of formal parameters (that is,
the compiler can deduce the template type from the actual arguments):
template<class T>
void g(T x)
{
// ...
}
Now if you want to force the actual arguments to be promoted before the compiler deduces the template type,
you can use the above technique. E.g., if you simply called g(42) you would get g<int>(42), but if you
wanted to pass 42 to g<long>(), you could say this: g<long>(42). (Of course you could also promote
the parameter explicitly, such as either g(long(42)) or even g(42L), but that ruins the example.)
Similarly if you said g("xyz") you'd end up calling g<char*>(char*), but if you wanted to call the
std::string version of g<>() you could say g<std::string>("xyz"). (Again you could also
promote the argument, such as g(std::string("xyz")), but that's another story.)
[ Top | Bottom | Previous section | Next section ]
[1.1] Author
Marshall Cline
[email protected]
not for commercial use, you must get permission from the author first (and that permission is normally
granted; note however that it's often easier for you to simply tell your recipients about the one-click
download option). In any event, all copies you make must retain verbatim and display conspicuously all
the following: all copyright notices, the Author section, the Copyright Notice section, the No Warranty
section, the C++-FAQ-Lite != C++-FAQ-Book section, and the Copy Permissions section.
If you want more and/or different privileges than are outlined here, please contact me,
[email protected]. I'm a very reasonable man...
[1.4] 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.
[ Top | Bottom | Next section ]
[1.5] Trademarks
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.
All other trademarks are the property of their respective owners.
Note: We'd like to list all trademarks explicitly; please let us know about who owns what trademark and
we'll name them explicitly; thanks!
[ Top | Bottom | Next section ]
[10] Constructors
(Part of C++ FAQ Lite, Copyright 1991-2001, Marshall Cline,
[email protected])
[10.10] Why are classes with static data members getting linker errors?
[10.11] What's the "static initialization order fiasco"?
[10.12] How do I prevent the "static initialization order fiasco"?
[10.13] How do I prevent the "static initialization order fiasco" for my static data members?
[10.14] How can I handle a constructor that fails?
[10.15] What is the "Named Parameter Idiom"?
class Fred {
public:
Fred(int i=3, int j=5); // Default constructor: can be called with no args
// ...
};
[ Top | Bottom | Previous section | Next section ]
int main()
{
Fred a[10]; // ERROR: Fred doesn't have a default constructor
Fred* p = new Fred[10]; // ERROR: Fred doesn't have a default constructor
}
However if you are constructing an object of the standard std::vector<Fred> rather than an array
of Fred (which you probably should be doing anyway since arrays are evil), you don't have to have a
default constructor in class Fred, since you can give the std::vector a Fred object to be used to
initialize the elements:
#include <vector>
int main()
{
std::vector<Fred> a(10, Fred(5,7));
// The 10 Fred objects in std::vector a will be initialized with Fred(5,7).
// ...
}
Even though you ought to use a std::vector rather than an array, there are times when an array
might be the right thing to do, and for those, there is the "explicit initialization of arrays" syntax. Here's
how it looks:
class Fred {
public:
Fred(int i, int j);
// ... assume there is no default constructor in class Fred ...
};
int main()
{
Fred a[10] = {
Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7),
Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7)
};
Initialization list. In fact, constructors should initialize all member objects in the initialization list.
For example, this constructor initializes member object x_ using an initialization list:
Fred::Fred() : x_(whatever) { }. The most common benefit of doing this is improved
performance. For example, if the expression whatever is the same as member variable x_, the result of
the whatever expression is constructed directly inside x_ the compiler does not make a separate copy
of the object. Even if the types are not the same, the compiler is usually able to do a better job with
initialization lists than with assignments.
The other (wrong) way to build constructors is via assignment, such as:
Fred::Fred() { x_ = whatever; }. In this case the expression whatever causes a separate,
temporary object to be created, and this temporary object is passed into the x_ object's assignment
operator. Then that temporary object is destructed at the ;. That's inefficient.
As if that wasn't bad enough, there's another source of inefficiency when using assignment in a
constructor: the member object will get full constructed by its default constructor, and this might, for
example, allocate some default amount of memory or open some default file. All this work could be for
naught if the whatever expression and/or assignment operator causes the object to close that file and/or
release that memory (e.g., if the default constructor didn't allocate a large enough pool of memory or if it
opened the wrong file).
Conclusion: All other things being equal, your code will run faster if you use initialization lists rather
than assignment.
Note: There is no performance difference if the type of x_ is some built-in/intrinsic type, such as int or
char* or float. But even in these cases, my personal preference is to set those data members in the
initialization list rather than via assignment for symmetry.
[ Top | Bottom | Previous section | Next section ]
Some people feel you should not use the this pointer in a constructor because the this object is not
fully formed yet. However you can use this in the constructor (in the {body} and even in the
initialization list) if you are careful.
Here is something that always works: the {body} of a constructor (or a function called from the
constructor) can reliably access the data members declared in a base class and/or the data members
declared in the constructor's own class. This is because all those data members are guaranteed to have
been fully constructed by the time the constructor's {body} starts executing.
Here is something that never works: the {body} of a constructor (or a function called from the
constructor) cannot get down to a derived class by calling a virtual member function that is
overridden in the derived class. If your goal was to get to the overridden function in the derived class,
you won't get what you want. Note that you won't get to the override in the derived class independent of
how you call the virtual member function: explicitly using the this pointer (e.g.,
this->method()), implicitly using the this pointer (e.g., method()), or even calling some other
function that calls the virtual member function on your this object. The bottom line is this: even if
the caller is constructing an object of a derived class, during the constructor of the base class, your object
is not yet of that derived class. You have been warned.
Here is something that sometimes works: if you pass any of the data members in this object to another
data member's initializer, you must make sure that the other data member has already been initialized.
The good news is that you can determine whether the other data member has (or has not) been initialized
using some straightforward language rules that are independent of the particular compiler you're using.
The bad news it that you have to know those language rules (e.g., base class sub-objects are initialized
first (look up the order if you have multiple and/or virtual inheritance!), then data members defined
in the class are initialized in the order in which they appear in the class declaration). If you don't know
these rules, then don't pass any data member from the this object (regardless of whether or not you
explicitly use the this keyword) to any other data member's initializer! And if you do know the rules,
please be careful.
[ Top | Bottom | Previous section | Next section ]
A technique that provides more intuitive and/or safer construction operations for users of your class.
The problem is that constructors always have the same name as the class. Therefore the only way to
differentiate between the various constructors of a class is by the parameter list. But if there are lots of
constructors, the differences between them become somewhat subtle and error prone.
With the Named Constructor Idiom, you declare all the class's constructors in the private: or
protected: sections, and you provide public static methods that return an object. These
static methods are the so-called "Named Constructors." In general there is one such static method
for each different way to construct an object.
For example, suppose we are building a Point class that represents a position on the X-Y plane. Turns
out there are two common ways to specify a 2-space coordinate: rectangular coordinates (X+Y), polar
coordinates (Radius+Angle). (Don't worry if you can't remember these; the point isn't the particulars of
coordinate systems; the point is that there are several ways to create a Point object.) Unfortunately the
parameters for these two coordinate systems are the same: two floats. This would create an ambiguity
error in the overloaded constructors:
class Point {
public:
Point(float x, float y); // Rectangular coordinates
Point(float r, float a); // Polar coordinates (radius and angle)
// ERROR: Overload is Ambiguous: Point::Point(float,float)
};
int main()
{
Point p = Point(5.7, 1.2); // Ambiguous: Which coordinate system?
}
One way to solve this ambiguity is to use the Named Constructor Idiom:
#include <cmath> // To get sin() and cos()
class Point {
public:
static Point rectangular(float x, float y); // Rectangular coord's
static Point polar(float radius, float angle); // Polar coordinates
Because you must explicitly define your class's static data members.
Fred.h:
class Fred {
public:
Fred();
// ...
private:
int i_;
static int j_;
};
Fred.cpp (or Fred.C or whatever):
Fred::Fred()
: i_(10) // OK: you can (and should) initialize member data this way
, j_(42) // Error: you cannot initialize static member data like this
{
// ...
}
[10.10] Why are classes with static data members getting linker
errors?
Because static data members must be explicitly defined in exactly one compilation unit. If you didn't
do this, you'll probably get an "undefined external" linker error. For example:
// Fred.h
class Fred {
public:
// ...
private:
static int j_; // Declares static data member Fred::j_
// ...
};
The linker will holler at you ("Fred::j_ is not defined") unless you define (as opposed to
merely declare) Fred::j_ in (exactly) one of your source files:
// Fred.cpp
#include "Fred.h"
// Alternatively, if you wish to use the implicit 0 value for static ints:
// int Fred::j_;
The usual place to define static data members of class Fred is file Fred.cpp (or Fred.C or
Note: The static initialization order fiasco does not apply to built-in/intrinsic types like int or char*.
For example if you create a static float object, there is never a problem with static initialization
order. The only time the static initialization order is truly a fiasco is when your static or global
objects have a constructor.
[ Top | Bottom | Previous section | Next section ]
// File y.cpp
#include "Barney.hpp"
Barney y;
For completeness the Barney constructor might look something like this:
// File Barney.cpp
#include "Barney.hpp"
Barney::Barney()
{
// ...
x.goBowling();
// ...
}
As described above, the disaster occurs if y is constructed before x, which happens 50% of the time
since they're in different source files.
There are many solutions to this problem, but a very simple and completely portable solution is to
replace the global Fred object, x, with a global function, x(), that returns the Fred object by
reference.
// File x.cpp
#include "Fred.hpp"
Fred& x()
{
static Fred* ans = new Fred();
return *ans;
}
Since static local objects are constructed the first time control flows over their declaration (only), the
above new Fred() statement will only happen once: the first time x() is called. Every subsequent
call will return the same Fred object (the one pointed to by ans). Then all you do is change your usages
of x to x():
// File Barney.cpp
#include "Barney.hpp"
Barney::Barney()
{
// ...
x().goBowling();
// ...
}
This is called the Construct On First Use Idiom because it does just that: the global Fred object is
constructed on its first use.
The downside of this approach is that the Fred object is never destructed. The C++ FAQ Book has a
second technique that answers this concern (but at the cost of opening a "static de-initialization order
fiasco").
Note: You don't have to do this for built-in/intrinsic types like int or char*. For example if you create
a static or global float object, there is no need to wrap it within a function. The only time the static
initialization order is truly a fiasco is when your static or global objects have a constructor.
[ Top | Bottom | Previous section | Next section ]
class X {
public:
// ...
private:
static Fred x_;
};
Naturally this static member is initialized separately:
// File X.cpp
#include "X.hpp"
Fred X::x_;
Naturally also the Fred object will be used in one or more of X's methods:
void X::someMethod()
{
x_.goBowling();
}
But now the "disaster scenario" is if someone somewhere somehow calls this method before the Fred
object gets constructed. For example, if someone else creates a static X object and invokes its
someMethod() method during static initialization, then you're at the mercy of the compiler as to
whether the compiler will construct X::x_ before or after the someMethod() is called. (Note that the
ANSI/ISO C++ committee is working on this problem, but compilers aren't yet generally available that
handle these changes; watch this space for an update in the future.)
In any event, it's always portable and safe to change the X::x_ static data member into a static
member function:
// File X.hpp
class X {
public:
// ...
private:
static Fred& x();
};
Naturally this static member is initialized separately:
// File X.cpp
#include "X.hpp"
Fred& X::x()
{
static Fred* ans = new Fred();
return *ans;
}
Then you simply change any usages of x_ to x():
void X::someMethod()
{
x().goBowling();
}
If you're super performance sensitive and you're concerned about the overhead of an extra function call
on each invocation of X::someMethod() you can set up a static Fred& instead. As you recall,
static local are only initialized once (the first time control flows over their declaration), so this will
call X::x() only once: the first time X::someMethod() is called:
void X::someMethod()
{
static Fred& x = X::x();
x.goBowling();
}
Note: You don't have to do this for built-in/intrinsic types like int or char*. For example if you create
a static or global float object, there is no need to wrap it within a function. The only time the static
initialization order is truly a fiasco is when your static or global objects have a constructor.
[ Top | Bottom | Previous section | Next section ]
The fundamental problem solved by the Named Parameter Idiom is that C++ only supports positional
parameters. For example, a caller of a function isn't allowed to say, "Here's the value for formal
parameter xyz, and this other thing is the value for formal parameter pqr." All you can do in C++ (and
C and Java) is say, "Here's the first parameter, here's the second parameter, etc." The alternative, called
named parameters and implemented in the language Ada, is especially useful if a function takes a large
number of mostly default-able parameters.
Over the years people have cooked up lots of workarounds for the lack of named parameters in C and
C++. One of these involves burying the parameter values in a string parameter then parsing this string at
run-time. This is what's done in the second parameter of fopen(), for example. Another workaround is
to combine all the boolean parameters in a bit-map, then the caller or's a bunch of bit-shifted constants
together to produce the actual parameter. This is what's done in the second parameter of open(), for
example. These approaches work, but the following technique produces caller-code that's more obvious,
easier to write, easier to read, and is generally more elegant.
The idea, called the Named Parameter Idiom, is to change the function's parameters to methods of a
newly created class, where all these methods return *this by reference. Then you simply rename the
main function into a parameterless "doit" method on that class.
We'll work an example to make the previous paragraph easier to understand.
The example will be for the "open a file" concept. Let's say that concept logically requires a parameter
for the file's name, and optionally allows parameters for whether the file should be opened read-only vs.
read-write vs. write-only, whether or not the file should be created if it doesn't already exist, whether the
writing location should be at the end ("append") or the beginning ("overwrite"), the block-size if the file
is to be created, whether the I/O is buffered or non-buffered, the buffer-size, whether it is to be shared vs.
exclusive access, and probably a few others. If we implemented this concept using a normal function
with positional parameters, the caller code would be very difficult to read: there'd be as many as 8
positional parameters, and the caller would probably make a lot of mistakes. So instead we use the
Named Parameter Idiom.
Before we go through the implementation, here's what the caller code might look like, assuming you are
willing to accept all the function's default parameters:
File f = OpenFile("foo.txt");
That's the easy case. Now here's what it might look like if you want to change a bunch of the parameters.
File f = OpenFile("foo.txt").
readonly().
createIfNotExist().
appendWhenWriting().
blockSize(1024).
unbuffered().
exclusiveAccess();
Notice how the "parameters", if it's fair to call them that, are in random order (they're not positional) and
they all have names. So the programmer doesn't have to remember the order of the parameters, and the
names are (hopefully) obvious.
So here's how to implement it: first we create a new class (OpenFile) that houses all the parameter
values as private: data members. Then all the methods (readonly(), blockSize(unsigned),
etc.) return *this (that is, they return a reference to the OpenFile object, allowing the method calls to
be chained. Finally we make the required parameter (the file's name, in this case) into a normal,
positional, parameter on OpenFile's constructor.
class File;
class OpenFile {
public:
OpenFile(const string& filename);
// sets all the default values for each data member
OpenFile& readonly(); // changes readonly_ to true
OpenFile& createIfNotExist();
OpenFile& blockSize(unsigned nbytes);
// ...
private:
friend File;
bool readonly_; // defaults to false [for example]
// ...
unsigned blockSize_; // defaults to 4096 [for example]
// ...
};
The only other thing to do is make the constructor for class File to take an OpenFile object:
class File {
public:
File(const OpenFile& params);
// ...
};
Note that OpenFile declares File as its friend, that way OpenFile doesn't need a bunch of
(otherwise useless) public: get methods.
[ Top | Bottom | Previous section | Next section ]
[11] Destructors
(Part of C++ FAQ Lite, Copyright 1991-2001, Marshall Cline,
[email protected])
can get really bad results from calling a destructor on the same object a second time! Bang! You're dead!
[ Top | Bottom | Previous section | Next section ]
[11.6] What if I want a local to "die" before the close } of the scope in
which it was created? Can I call a destructor on a local if I really want
to?
No! [For context, please read the previous FAQ].
Suppose the (desirable) side effect of destructing a local File object is to close the File. Now suppose
you have an object f of a class File and you want File f to be closed before the end of the scope (i.e.,
the }) of the scope of object f:
void someCode()
{
File f;
// ... [This code that should execute when f is still open] ...
Simply wrap the extent of the lifetime of the local in an artificial block {...}:
void someCode()
{
{
File f;
// ... [This code will execute when f is still open] ...
}
// ^ f's destructor will automagically be called here!
File::~File()
{
close();
}
void File::close()
{
if (fileHandle_ >= 0) {
// ... [Perform some operating-system call to close the file] ...
fileHandle_ = -1;
}
}
Note that the other File methods may also need to check if the fileHandle_ is -1 (i.e., check if the
File is closed).
Note also that any constructors that don't actually open a file should set fileHandle_ to -1.
[ Top | Bottom | Previous section | Next section ]
void someCode()
{
char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2
// ...
}
Line #1 creates an array of sizeof(Fred) bytes of memory, which is big enough to hold a Fred
object. Line #2 creates a pointer place that points to the first byte of this memory (experienced C
programmers will note that this step was unnecessary; it's there only to make the code more obvious).
Line #3 essentially just calls the constructor Fred::Fred(). The this pointer in the Fred
constructor will be equal to place. The returned pointer f will therefore be equal to place.
ADVICE: Don't use this "placement new" syntax unless you have to. Use it only when you really care
that an object is placed at a particular location in memory. For example, when your hardware has a
memory-mapped I/O timer device, and you want to place a Clock object at that memory location.
DANGER: You are taking sole responsibility that the pointer you pass to the "placement new"
operator points to a region of memory that is big enough and is properly aligned for the object type
that you're creating. Neither the compiler nor the run-time system make any attempt to check whether
you did this right. If your Fred class needs to be aligned on a 4 byte boundary but you supplied a
location that isn't properly aligned, you can have a serious disaster on your hands (if you don't know what
"alignment" means, please don't use the placement new syntax). You have been warned.
You are also solely responsible for destructing the placed object. This is done by explicitly calling the
destructor:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
// ...
f->~Fred(); // Explicitly call the destructor for the placed object
}
This is about the only time you ever explicitly call a destructor.
[ Top | Bottom | Previous section | Next section ]
class Fred {
public:
~Fred();
// ...
private:
Member x_;
Member y_;
Member z_;
};
Fred::~Fred()
{
// Compiler automagically calls z_.~Member()
// Compiler automagically calls y_.~Member()
// Compiler automagically calls x_.~Member()
}
[ Top | Bottom | Previous section | Next section ]
class Base {
public:
virtual ~Base(); // A virtual destructor
// ...
};
Derived::~Derived()
{
// Compiler automagically calls x_.~Member()
// Compiler automagically calls Base::~Base()
}
Note: Order dependencies with virtual inheritance are trickier. If you are relying on order
dependencies in a virtual inheritance hierarchy, you'll need a lot more information than is in this
FAQ.
[ Top | Bottom | Previous section | Next section ]
A member function declaration that turns a normal class into an abstract class (i.e., an ABC). You
normally only implement it in a derived class.
Some member functions exist in concept; they don't have any reasonable definition. E.g., suppose I asked
you to draw a Shape at location (x,y) that has size 7. You'd ask me "what kind of shape should I
draw?" (circles, squares, hexagons, etc, are drawn differently). In C++, we must indicate the existence of
the draw() member function (so users can call it when they have a Shape* or a Shape&), but we
recognize it can (logically) be defined only in derived classes:
class Shape {
public:
virtual void draw() const = 0; // = 0 means it is "pure virtual"
// ...
};
This pure virtual function makes Shape an ABC. If you want, you can think of the "= 0;" syntax as if
the code were at the NULL pointer. Thus Shape promises a service to its users, yet Shape isn't able to
provide any code to fulfill that promise. This forces any actual object created from a [concrete] class
derived from Shape to have the indicated member function, even though the base class doesn't have
enough information to actually define it yet.
Note that it is possible to provide a definition for a pure virtual function, but this usually confuses
novices and is best avoided until later.
[3.1] Is there a C++ FAQ Book in addition to the C++ FAQ Lite?
[Recently added BookPool.com and AllDirect.com thanks to Stan Brown, plus reorganized (on 7/00). Click here to go to
the next FAQ in the "chain" of recent changes.]
Yes, the book is C++ FAQs by Cline, Lomow, and Girou, Addison-Wesley, 1999, ISBN 0-201-30983-1.
The book has achieved a five-star rating ( ) on Amazon.com, and is available in bookstores.
Here is the cover:
[3.2] Is there a big difference between C++ FAQ Lite and C++ FAQ
Book?
[Recently changed 'much' to 'many' thanks to Stan Brown (on 7/00). Click here to go to the next FAQ in the "chain" of
recent changes.]
[16.2] Can I free() pointers allocated with new? Can I delete pointers
allocated with malloc()?
No!
It is perfectly legal, moral, and wholesome to use malloc() and delete in the same program, or to use new and
free() in the same program. But it is illegal, immoral, and despicable to call free() with a pointer allocated via
new, or to call delete on a pointer allocated via malloc().
Beware! I occasionally get e-mail from people telling me that it works OK for them on machine X and compiler Y. That
does not make it right! Sometimes people say, "But I'm just working with an array of char." Nonetheless do not mix
malloc() and delete on the same pointer, or new and free() on the same pointer! If you allocated via
p = new char[n], you must use delete[] p; you must not use free(p). Or if you allocated via
p = malloc(n), you must use free(p); you must not use delete[] p or delete p! Mixing these up could
cause a catastrophic failure at runtime if the code was ported to a new machine, a new compiler, or even a new version of
the same compiler.
You have been warned.
[ Top | Bottom | Previous section | Next section ]
No! (But if you have an old compiler, you may have to force the new operator to throw an exception if it runs out of
memory.)
It turns out to be a real pain to always write explicit NULL tests after every new allocation. Code like the following is
very tedious:
Fred* p = new Fred();
if (p == NULL)
throw std::bad_alloc();
If your compiler doesn't support (or if you refuse to use) exceptions, your code might be even more tedious:
void myNewHandler()
{
// This is your own handler. It can do anything you want.
throw alloc_error();
}
int main()
{
std::set_new_handler(myNewHandler); // Install your "new handler"
// ...
}
After the std::set_new_handler() line is executed, operator new will call your myNewHandler()
if/when it runs out of memory. This means that new will never return NULL:
Fred* p = new Fred(); // No need to check if p is NULL
Note: If your compiler doesn't support exception handling, you can, as a last resort, change the line throw ...; to:
[16.8] What are the two steps that happen when I say delete p?
delete p is a two-step process: it calls the destructor, then releases the memory. The code generated for delete p
looks something like this (assuming p is of type Fred*):
// Original code: delete p;
if (p != NULL) {
p->~Fred();
operator delete(p);
}
The statement p->~Fred() calls the destructor for the Fred object pointed to by p.
The statement operator delete(p) calls the memory deallocation primitive,
void operator delete(void* p). This primitive is similar in spirit to free(void* p). (Note, however,
that these two are not interchangeable; e.g., there is no guarantee that the two memory deallocation primitives even use
the same heap!).
[ Top | Bottom | Previous section | Next section ]
[16.9] In p = new Fred(), does the Fred memory "leak" if the Fred
constructor throws an exception?
No.
If an exception occurs during the Fred constructor of p = new Fred(), the C++ language guarantees that the
memory sizeof(Fred) bytes that were allocated will automagically be released back to the heap.
Here are the details: new Fred() is a two-step process:
1. sizeof(Fred) bytes of memory are allocated using the primitive
void* operator new(size_t nbytes). This primitive is similar in spirit to
malloc(size_t nbytes). (Note, however, that these two are not interchangeable; e.g., there is no guarantee
that the two memory allocation primitives even use the same heap!).
2. It constructs an object in that memory by calling the Fred constructor. The pointer returned from the first step is
passed as the this parameter to the constructor. This step is wrapped in a try ... catch block to handle the case
when an exception is thrown during this step.
Thus the actual generated code looks something like:
// Original code: Fred* p = new Fred();
Fred* p = (Fred*) operator new(sizeof(Fred));
try {
new(p) Fred(); // Placement new
} catch (...) {
operator delete(p); // Deallocate the memory
throw; // Re-throw the exception
}
The statement marked "Placement new" calls the Fred constructor. The pointer p becomes the this pointer inside the
constructor, Fred::Fred().
[16.11] What if I forget the [] when deleteing array allocated via new T[n]?
All life comes to a catastrophic end.
It is the programmer's not the compiler's responsibility to get the connection between new T[n] and
delete[] p correct. If you get it wrong, neither a compile-time nor a run-time error message will be generated by the
compiler. Heap corruption is a likely result. Or worse. Your program will probably die.
[ Top | Bottom | Previous section | Next section ]
[16.12] Can I drop the [] when deleteing array of some built-in type (char,
int, etc)?
No!
Sometimes programmers think that the [] in the delete[] p only exists so the compiler will call the appropriate
destructors for all elements in the array. Because of this reasoning, they assume that an array of some built-in type such
as char or int can be deleted without the []. E.g., they assume the following is valid code:
void userCode(int n)
{
char* p = new char[n];
// ...
delete p; // < ERROR! Should be delete[] p !
}
But the above code is wrong, and it can cause a disaster at runtime. In particular, the code that's called for delete p is
operator delete(void*), but the code that's called for delete[] p is operator delete[](void*).
The default behavior for the latter is to call the former, but users are allowed to replace the latter with a different
behavior (in which case they would normally also replace the corresponding new code in
operator new[](size_t)). If they replaced the delete[] code so it wasn't compatible with the delete code,
and you called the wrong one (i.e., if you said delete p rather than delete[] p), you could end up with a disaster
at runtime.
[ Top | Bottom | Previous section | Next section ]
[16.13] After p = new Fred[n], how does the compiler know there are n
objects to be destructed during delete[] p?
[Recently changed "popluar" to "popular" thanks to Fabrice Clerc (on 7/00). Click here to go to the next FAQ in the "chain" of recent
changes.]
[16.14] Is it legal (and moral) for a member function to say delete this?
As long as you're careful, it's OK for an object to commit suicide (delete this).
Here's how I define "careful":
1. You must be absolutely 100% positive sure that this object was allocated via new (not by new[], nor by
placement new, nor a local object on the stack, nor a global, nor a member of another object; but by plain ordinary
new).
2. You must be absolutely 100% positive sure that your member function will be the last member function invoked
on this object.
3. You must be absolutely 100% positive sure that the rest of your member function (after the delete this line)
doesn't touch any piece of this object (including calling any other member functions or touching any data
members).
4. You must be absolutely 100% positive sure that no one even touches the this pointer itself after the delete
this line. In other words, you must not examine it, compare it with another pointer, compare it with NULL, print
it, cast it, do anything with it.
Naturally the usual caveats apply in cases where your this pointer is a pointer to a base class when you don't have a
virtual destructor.
There are many ways to do this, depending on how flexible you want the array sizing to be. On one extreme, if you know
all the dimensions at compile-time, you can allocate multidimensional arrays statically (as in C):
class Fred { /*...*/ };
void someFunction(Fred& fred);
void manipulateArray()
{
const unsigned nrows = 10; // Num rows is a compile-time constant
// ...
}
catch (...) {
// Make sure to do the delete when an exception is thrown:
delete[] matrix;
throw; // Re-throw the current exception
}
delete[] matrix;
}
Finally at the other extreme, you may not even be guaranteed that the matrix is rectangular. For example, if each row
could have a different length, you'll need to allocate each row individually. In the following function, ncols[i] is the
number of columns in row number i, where i varies between 0 and nrows-1 inclusive.
void manipulateArray(unsigned nrows, unsigned ncols[])
{
typedef Fred* FredPtr;
// ...
}
catch (...) {
// Make sure to do the delete when an exception is thrown:
// Note that some of these matrix[...] pointers might be
// NULL, but that's okay since it's legal to delete NULL.
for (unsigned i = nrows; i > 0; --i)
delete[] matrix[i-1];
delete[] matrix;
throw; // Re-throw the current exception
}
[16.16] But the previous FAQ's code is SOOOO tricky and error prone! Isn't
there a simpler way?
[Recently clarified the last paragraph (on 7/00) and fixed the Star Trek movie number thanks to Chris Sheppard (on 4/01) and wordsmithed
last paragraph at the suggestion of prapp (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
Yep.
The reason the code in the previous FAQ was so tricky and error prone was that it used pointers, and we know that
pointers and arrays are evil. The solution is to encapsulate your pointers in a class that has a safe and simple interface.
For example, we can define a Matrix class that handles a rectangular matrix so our user code will be vastly simplified
when compared to the the rectangular matrix code from the previous FAQ:
The main thing to notice is the lack of clean-up code. For example, there aren't any delete statements in the above
code, yet there will be no memory leaks, assuming only that the Matrix destructor does its job correctly.
Here's the Matrix code that makes the above possible:
class Matrix {
public:
Matrix(unsigned nrows, unsigned ncols);
// Throws a BadSize object if either size is zero
class BadSize { };
private:
Fred* data_;
unsigned nrows_, ncols_;
};
Matrix::~Matrix()
{
delete[] data_;
}
Note that the above Matrix class accomplishes two things: it moves some tricky memory management code from the
user code (e.g., main()) to the class, and it reduces the overall bulk of program. The latter point is important. For
example, assuming Matrix is even mildly reusable, moving complexity from the users [plural] of Matrix into
Matrix itself [singular] is equivalent to moving complexity from the many to the few. Anyone who's seen Star Trek 2
knows that the good of the many outweighs the good of the few... or the one.
[ Top | Bottom | Previous section | Next section ]
[16.17] But the above Matrix class is specific to Fred! Isn't there a way to
make it generic?
[Recently rewrote (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
private:
T* data_;
unsigned nrows_, ncols_;
};
template<class T>
inline T& Matrix<T>::operator() (unsigned row, unsigned col)
{
if (row >= nrows_ || col >= ncols_) throw BoundsViolation();
return data_[row*ncols_ + col];
}
template<class T>
inline const T& Matrix<T>::operator() (unsigned row, unsigned col) const
{
if (row >= nrows_ || col >= ncols_) throw BoundsViolation();
return data_[row*ncols_ + col];
}
template<class T>
inline Matrix<T>::Matrix(unsigned nrows, unsigned ncols)
: data_ (new T[nrows * ncols])
, nrows_ (nrows)
, ncols_ (ncols)
{
if (nrows == 0 || ncols == 0)
throw BadSize();
}
template<class T>
inline Matrix<T>::~Matrix()
{
delete[] data_;
}
[ Top | Bottom | Previous section | Next section ]
private:
vector<vector<T> > data_;
};
template<class T>
inline T& Matrix<T>::operator() (unsigned row, unsigned col)
{
if (row >= nrows_ || col >= ncols_) throw BoundsViolation();
return data_[row][col];
template<class T>
inline const T& Matrix<T>::operator() (unsigned row, unsigned col) const
{
if (row >= nrows_ || col >= ncols_) throw BoundsViolation();
return data_[row][col];
}
template<class T>
Matrix<T>::Matrix(unsigned nrows, unsigned ncols)
: data_ (nrows)
{
if (nrows == 0 || ncols == 0)
throw BadSize();
for (unsigned i = 0; i < nrows; ++i)
data_[i].resize(ncols);
}
[ Top | Bottom | Previous section | Next section ]
[16.19] Does C++ have arrays whose length can be specified at run-time?
[Recently changed so it uses new-style headers and the std:: syntax and reworded references to STL (on 7/00). Click here to go to the next
FAQ in the "chain" of recent changes.]
Yes, in the sense that the standard library has a std::vector template that provides this behavior.
No, in the sense that built-in array types need to have their length specified at compile time.
Yes, in the sense that even built-in array types can specify the first index bounds at run-time. E.g., comparing with the
previous FAQ, if you only need the first array dimension to vary then you can just ask new for an array of arrays, rather
than an array of pointers to arrays:
const unsigned ncols = 100; // ncols = number of columns in the array
[16.20] How can I force objects of my class to always be created via new rather
than as locals or global/static objects?
Use the Named Constructor Idiom.
As usual with the Named Constructor Idiom, the constructors are all private: or protected:, and there are one or
more public static create() methods (the so-called "named constructors"), one per constructor. In this case the
create() methods allocate the objects via new. Since the constructors themselves are not public, there is no other
way to create objects of the class.
class Fred {
public:
// The create() methods are the "named constructors":
static Fred* create() { return new Fred(); }
static Fred* create(int i) { return new Fred(i); }
static Fred* create(const Fred& fred) { return new Fred(fred); }
// ...
private:
// The constructors themselves are private or protected:
Fred();
Fred(int i);
Fred(const Fred& fred);
// ...
};
Now the only way to create Fred objects is via Fred::create():
int main()
{
Fred* p = Fred::create(5);
// ...
delete p;
}
Make sure your constructors are in the protected: section if you expect Fred to have derived classes.
Note also that you can make another class Wilma a friend of Fred if you want to allow a Wilma to have a member
object of class Fred, but of course this is a softening of the original goal, namely to force Fred objects to be allocated
via new.
[ Top | Bottom | Previous section | Next section ]
If all you want is the ability to pass around a bunch of pointers to the same object, with the feature that the object will
automagically get deleted when the last pointer to it disappears, you can use something like the following "smart
pointer" class:
// Fred.h
class FredPtr;
class Fred {
public:
Fred() : count_(0) /*...*/ { } // All ctors set count_ to 0 !
// ...
private:
friend FredPtr; // A friend class
unsigned count_;
// count_ must be initialized to 0 by all constructors
// count_ is the number of FredPtr objects that point at this
};
class FredPtr {
public:
Fred* operator-> () { return p_; }
Fred& operator* () { return *p_; }
FredPtr(Fred* p) : p_(p) { ++p_->count_; } // p must not be NULL
~FredPtr() { if (--p_->count_ == 0) delete p_; }
FredPtr(const FredPtr& p) : p_(p.p_) { ++p_->count_; }
FredPtr& operator= (const FredPtr& p)
{ // DO NOT CHANGE THE ORDER OF THESE STATEMENTS!
// (This order properly handles self-assignment)
++p.p_->count_;
if (--p_->count_ == 0) delete p_;
p_ = p.p_;
return *this;
}
private:
Fred* p_; // p_ is never NULL
};
Naturally you can use nested classes to rename FredPtr to Fred::Ptr.
Note that you can soften the "never NULL" rule above with a little more checking in the constructor, copy constructor,
assignment operator, and destructor. If you do that, you might as well put a p_ != NULL check into the "*" and "->"
operators (at least as an assert()). I would recommend against an operator Fred*() method, since that would
let people accidentally get at the Fred*.
One of the implicit constraints on FredPtr is that it must only point to Fred objects which have been allocated via
new. If you want to be really safe, you can enforce this constraint by making all of Fred's constructors private, and
for each constructor have a public (static) create() method which allocates the Fred object via new and
returns a FredPtr (not a Fred*). That way the only way anyone could create a Fred object would be to get a
FredPtr ("Fred* p = new Fred()" would be replaced by "FredPtr p = Fred::create()"). Thus no
one could accidentally subvert the reference counted mechanism.
For example, if Fred had a Fred::Fred() and a Fred::Fred(int i, int j), the changes to class Fred
would be:
class Fred {
public:
static FredPtr create(); // Defined below class FredPtr {...}
static FredPtr create(int i, int j); // Defined below class FredPtr {...}
// ...
private:
Fred();
Fred(int i, int j);
// ...
};
[Recently rewrote the first paragraph for clarity thanks to Fabrice Clerc (on 7/00). Click here to go to the next FAQ in the "chain" of recent
changes.]
Reference counting can be done with either pointer semantics or reference semantics. The previous FAQ shows how to
do reference counting with pointer semantics. This FAQ shows how to do reference counting with reference semantics.
The basic idea is to allow users to think they're copying your Fred objects, but in reality the underlying implementation
doesn't actually do any copying unless and until some user actually tries to modify the underlying Fred object.
Class Fred::Data houses all the data that would normally go into the Fred class. Fred::Data also has an extra
data member, count_, to manage the reference counting. Class Fred ends up being a "smart reference" that
(internally) points to a Fred::Data.
class Fred {
public:
// ...
private:
class Data {
public:
Data();
Data(int i, int j);
Data(const Data& d);
unsigned count_;
// count_ is the number of Fred objects that point at this
// count_ must be initialized to 1 by all constructors
// (it starts as 1 since it is pointed to by the Fred object that created it)
};
Data* data_;
};
Fred::Fred(const Fred& f)
: data_(f.data_)
{
++ data_->count_;
}
Fred::~Fred()
{
if (--data_->count_ == 0) delete data_;
}
// Other than that, any data access would simply use "data_->..."
}
void Fred::sampleMutatorMethod()
{
// This method might need to change things in *data_
// Thus it first checks if this is the only pointer to *data_
if (data_->count_ > 1) {
Data* d = new Data(*data_); // Invoke Fred::Data's copy ctor
-- data_->count_;
data_ = d;
}
assert(data_->count_ == 1);
Fred::Fred()
: data_(defaultData())
{
++ data_->count_;
}
Fred::Data* Fred::defaultData()
{
static Data* p = NULL;
if (p == NULL) {
p = new Data();
++ p->count_; // Make sure it never goes to zero
}
return p;
}
Note: You can also provide reference counting for a hierarchy of classes if your Fred class would normally have been a
base class.
[ Top | Bottom | Previous section | Next section ]
The previous FAQ presented a reference counting scheme that provided users with reference semantics, but did so for a
single class rather than for a hierarchy of classes. This FAQ extends the previous technique to allow for a hierarchy of
classes. The basic difference is that Fred::Data is now the root of a hierarchy of classes, which probably cause it to
have some virtual functions. Note that class Fred itself will still not have any virtual functions.
The Virtual Constructor Idiom is used to make copies of the Fred::Data objects. To select which derived class to
create, the sample code below uses the Named Constructor Idiom, but other techniques are possible (a switch
statement in the constructor, etc). The sample code assumes two derived classes: Der1 and Der2. Methods in the
derived classes are unaware of the reference counting.
class Fred {
public:
// ...
private:
class Data {
public:
Data() : count_(1) { }
Data(const Data& d) : count_(1) { } // Do NOT copy the 'count_' member!
Data& operator= (const Data&) { return *this; } // Do NOT copy the 'count_' member!
virtual ~Data() { assert(count_ == 0); } // A virtual destructor
virtual Data* clone() const = 0; // A virtual constructor
virtual void sampleInspectorMethod() const = 0; // A pure virtual function
virtual void sampleMutatorMethod() = 0;
private:
unsigned count_; // count_ doesn't need to be protected
friend Fred; // Allow Fred to access count_
};
Fred(Data* data);
// Creates a Fred smart-reference that owns *data
// It is private to force users to use a createXXX() method
// Requirement: data must not be NULL
Fred::Fred(const Fred& f)
: data_(f.data_)
{
++ data_->count_;
}
Fred::~Fred()
{
if (--data_->count_ == 0) delete data_;
}
void Fred::sampleMutatorMethod()
{
// This method might need to change things in *data_
// Thus it first checks if this is the only pointer to *data_
if (data_->count_ > 1) {
Data* d = data_->clone(); // The Virtual Constructor Idiom
-- data_->count_;
data_ = d;
}
assert(data_->count_ == 1);
[16.24] Can you absolutely prevent people from subverting the reference
counting mechanism, and if so, should you?
[Recently created (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
have a dangling pointer shudder. This hole could be plugged by preventing people from taking the address of a
FredPtr (by overloading FredPtr::operator&() as private), with the corresponding loss of
functionality. But even if you did all that, they could still create a FredPtr& which is almost as dangerous as a
FredPtr*, simply by doing this: FredPtr p; ... FredPtr& q = p; (or by passing the FredPtr& to
someone else).
And even if we closed all those holes, C++ has those wonderful pieces of syntax called pointer casts. Using a pointer
cast or two, a sufficiently motivated programmer can normally create a hole that's big enough to drive a proverbial truck
through.
So the lessons here seems to be: (a) you can't prevent espionage no matter how hard you try, and (b) you can easily
prevent mistakes.
So I recommend settling for the "low hanging fruit": use the easy-to-build and easy-to-use mechanisms that prevent
mistakes, and don't bother trying to prevent espionage. You won't succeed, and even if you do, it'll (probably) cost you
more than it's worth.
So if we can't use the C++ language itself to prevent espionage, are there other ways to do it? Yes. I personally use old
fashioned code-reviews for that. And since the espionage techniques usually involve some bizarre syntax and/or use of
pointer-casts and unions, you can use a tool to point out most of the "hot spots."
[ Top | Bottom | Previous section | Next section ]
Yes.
Compared with the "smart pointer" techniques, such as are described above, the garbage collector techniques are:
less portable
usually more efficient (especially when the average object size is small or in multithreaded environments)
able to handle "cycles" in the data (reference counting techniques normally "leak" if the data structures can form a
cycle)
sometimes leak other objects (since the garbage collectors are necessarily conservative, they sometimes see a
random bit pattern that appears to be a pointer into an allocation, especially if the allocation is large; this can allow
the allocation to leak)
work better with existing libraries (since smart pointers need to be used explicitly, they may be hard to integrate
with existing libraries)
[ Top | Bottom | Previous section | Next section ]
[16.26] What are the two kinds of garbage collectors for C++?
[Recently created thanks to Hans Boehm (on 7/00) and added a URL for Bartlett's collector thanks to Abhishek (on 4/01). Click here to go to
the next FAQ in the "chain" of recent changes.]
2. Hybrid garbage collectors. These usually scan the stack conservatively, but require the programmer to supply
layout information for heap objects. This requires more work on the programmer's part, but may result in
improved performance. Here are some examples, in alphabetical order:
Bartlett's mostly copying collector
Attardi and Flagella's CMM (if someone has a URL, please send it to me).
Since garbage collectors for C++ are normally conservative, they can sometimes leak if a bit pattern "looks like" it might
be a pointer to an otherwise unused block. Also they sometimes get confused when pointers to a block actually point
outside the block's extent (which is illegal, but some programmers simply must push the envelope; sigh) and (rarely)
when a pointer is hidden by a compiler optimization. In practice these problems are not usually serious, however
providing the collector with hints about the layout of the objects can sometimes ameliorate these issues.
[ Top | Bottom | Previous section | Next section ]
[16.27] Where can I get more info on garbage collectors for C++?
[Recently created (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
[14] Friends
(Part of C++ FAQ Lite, Copyright 1991-2001, Marshall Cline,
[email protected])
"makes sense" from outside the class (from a user's perspective). In many cases, these get()/set()
member functions are almost as bad as public data: they hide (only) the name of the private datum,
but they don't hide the existence of the private datum.
Similarly, if you use friend functions as a syntactic variant of a class's public: access functions, they
don't violate encapsulation any more than a member function violates encapsulation. In other words, a
class's friends don't violate the encapsulation barrier: along with the class's member functions, they are
the encapsulation barrier.
[ Top | Bottom | Previous section | Next section ]
};
void userCode(Base& b)
{
f(b);
}
The statement f(b) in userCode(Base&) will invoke b.do_f(), which is virtual. This means
that Derived::do_f() will get control if b is actually a object of class Derived. Note that
Derived overrides the behavior of the protected: virtual member function do_f(); it does
not have its own variation of the friend function, f(Base&).
[ Top | Bottom | Previous section | Next section ]
Just because I grant you friendship access to me doesn't automatically grant your kids access to me,
doesn't automatically grant your friends access to me, and doesn't automatically grant me access to you.
I don't necessarily trust the kids of my friends. The privileges of friendship aren't inherited.
Derived classes of a friend aren't necessarily friends. If class Fred declares that class Base
is a friend, classes derived from Base don't have any automatic special access rights to Fred
objects.
I don't necessarily trust the friends of my friends. The privileges of friendship aren't transitive. A
friend of a friend isn't necessarily a friend. If class Fred declares class Wilma as a friend,
and class Wilma declares class Betty as a friend, class Betty doesn't necessarily have
any special access rights to Fred objects.
You don't necessarily trust me simply because I declare you my friend. The privileges of
friendship aren't reciprocal. If class Fred declares that class Wilma is a friend, Wilma objects
have special access to Fred objects but Fred objects do not automatically have special access to
Wilma objects.
[ Top | Bottom | Previous section | Next section ]
the binary infix arithmetic operators. E.g., aComplex + aComplex should be defined as a friend
rather than a member if you want to allow aFloat + aComplex as well (member functions don't
allow promotion of the left hand argument, since that would change the class of the object that is the
recipient of the member function invocation).
In other cases, choose a member function over a friend function.
[ Top | Bottom | Previous section | Next section ]
If you want to learn OO/C++, learn OO/C++. Taking time out to learn C will waste your time and
confuse you.
[ Top | Bottom | Previous section | Next section ]
Knowing a "pure" OO language doesn't make the transition to OO/C++ any easier. This is not a theory;
we have trained and mentored literally thousands of software professionals in OO. In fact, Smalltalk
experience can make it harder for some people: they need to unlearn some rather deep notions about
typing and inheritance in addition to needing to learn new syntax and idioms. This unlearning process is
especially painful and slow for those who cling to Smalltalk with religious zeal ("C++ is not like
Smalltalk, therefore C++ is evil").
If you want to learn OO/C++, learn OO/C++. Taking time out to learn Smalltalk will waste your time
and confuse you.
Note: I sit on both the ANSI C++ (X3J16) and ANSI Smalltalk (X3J20) standardization committees. I
am not a language bigot. I'm not saying C++ is better or worse than Smalltalk; I'm simply saying that
they are different.
At least three.
There are three categories of insight and knowledge in OO programming using C++. You should get a
great book from each category, not an okay book that tries to do an okay job at everything. The three
OO/C++ programming categories are:
C++ legality guides what you can and can't do in C++.
Legality guides describe all language features with roughly the same level of emphasis; morality guides
focus on those language features that you will use most often in typical programming tasks. Legality
guides tell you how to get a given feature past the compiler; morality guides tell you whether or not to
use that feature in the first place.
Meta comments:
Neither of these categories is optional. You must have a good grasp of both.
These categories do not trade off against each other. You shouldn't argue in favor of one over the
other. They dove-tail.
There is a fourth category you should consider in addition to the above three: OO Design books. These
are books that focus on how to think and design with objects.
[ Top | Bottom | Previous section | Next section ]
[5.1] What does IMHO mean? (or IMO, IMNSHO, FWIW, OTOH, etc.)?
Here's a partial list of acronyms in alphabetical order:
AFAICS = As far as I can see
BTW my SO says, "FWIW IMNSHO 'KUTGW' is rare; OTOH it may be helpful to somebody."
For more acronyms please see www.astro.umd.edu/~marshall/abbrev.html.
[ Top | Bottom | Previous section | Next section ]
[Recently added stuff about the evils of asking others to do your homework for you via email (on 4/01). Click here to go to
the next FAQ in the "chain" of recent changes.]
Shame on you!
Please do not post your homework questions to comp.lang.c++. And don't send them to people via email
either!
[ Top | Bottom | Previous section | Next section ]
[If anyone has other suggestions that should go into this table, please let me know; thanks;
([email protected])].
[5.4] How can I find out about general netiquette so I don't embarrass
myself?
Key guidelines:
Do not say, "Please respond by e-mail because I don't normally read this
newsgroup". If you don't have enough time for the newsgroup, don't expect the newsgroup to
have enough time for you.
Do not post questions that are answered in the newsgroup's FAQ. That's like saying your time (to
read the FAQ) is more valuable than the time of hundreds and hundreds of others (to answer your
question). Tres uncool. Read the FAQ first!
Do not cross post your question to a big pile of newsgroups. Post to the newsgroup (singular) that
best fits your question. If you don't get an answer in the "right" newsgroup, post somewhere else
but redirect followups back to the "right" newsgroup.
Do include a working e-mail address in your signature. If your From: address is not correct,
please notify your system administrator. Until it's fixed, add a Reply-to: line that gives your
correct e-mail address.
Many more general netiquette questions are answered in the newsgroup
news.announce.newusers. This newsgroup contains many must-read articles for new users.
[ Top | Bottom | Previous section | Next section ]
Note #2: Please be polite. I'm hoping we can avoid "RTFM" or "RTFFAQ" euphemisms (or worse!).
Thanks for any help you can give in this matter.
[ Top | Bottom | Previous section | Next section ]
comp.lang.c++.
Here are some other potentially relevant newsgroups:
comp.lang.c++.moderated
comp.os.ms-windows.programmer.tools.*
This group is intended for discussions about the selection and use of tools for Windows
software development
comp.os.ms-windows.programmer.misc
This group is for all other discussions about Windows software development
comp.os.msdos.programmer
Much of the traffic is about language products, chiefly from Borland and Microsoft
Note: The FAQ for this group is not available at rtfm.mit.edu; it is at
ftp://oak.oakland.edu/pub/msdos/info and
ftp://garbo.uwasa.fi/pc/doc-net
Sample topic: How can I read a character without [waiting for] the Enter key?
Sample topic: How can I read, create, change, or delete the volume label?
Sample topic: How do I configure a COM port and use it to transmit data?
Sample topic: How can I find the Microsoft mouse position and button status?
comp.os.msdos.programmer.turbovision
comp.unix.programmer
Sample topic: How do I use popen() to open a process for reading and writing?
Sample topic: How do I sleep() in a C program for less than one second?
comp.unix.solaris
Covers SunOS 4.x and Solaris
gnu.g++.help
Sample topic: Where can I find a demangler?
gnu.g++.bug
Bug reports for g++; see the g++ docs
comp.lang.c
FAQ is posted monthly, and is maintained by Steve Summit
Sample topic: I'm confused. NULL is guaranteed to be 0, but the null pointer is not?
Sample topic: How can I write a function that takes a variable number of arguments?
[stdarg.h or varargs.h]
Sample topic: How do I declare an array of pointers to functions returning pointers to
functions returning pointers to characters?
comp.graphics
Issues revolving around graphics programming
comp.sources.wanted
If you want some source code for something, post your request there
comp.programming
General programming issues
[ Top | Bottom | Previous section | Next section ]
ftp: ftp://rtfm.mit.edu/pub/usenet/
e-mail: send a message with the line "help" to [email protected]
usenet: many FAQs are available in the newsgroup news.answers
Please, PLEASE do not send e-mail to me!
[ Top | Bottom | Previous section | Next section ]
[9.4] How do you tell the compiler to make a non-member function inline?
[9.5] How do you tell the compiler to make a member function inline?
[9.6] Is there another way to tell the compiler to make a member function inline?
[9.7] Are inline functions guaranteed to make your performance better?
[9.2] How can inline functions help with the tradeoff of safety vs.
speed?
In straight C, you can achieve "encapsulated structs" by putting a void* in a struct, in which case
the void* points to the real data that is unknown to users of the struct. Therefore users of the
struct don't know how to interpret the stuff pointed to by the void*, but the access functions cast the
void* to the approprate hidden type. This gives a form of encapsulation.
Unfortunately it forfeits type safety, and also imposes a function call to access even trivial fields of the
struct (if you allowed direct access to the struct's fields, anyone and everyone would be able to get
direct access since they would of necessity know how to interpret the stuff pointed to by the void*; this
would make it difficult to change the underlying data structure).
Function call overhead is small, but can add up. C++ classes allow function calls to be expanded
inline. This lets you have the safety of encapsulation along with the speed of direct access.
Furthermore the parameter types of these inline functions are checked by the compiler, an
improvement over C's #define macros.
[ Top | Bottom | Previous section | Next section ]
[9.3] Why should I use inline functions? Why not just use plain old
#define macros?
[Recently rewrote the sentence on #define being evil (on 7/00). Click here to go to the next FAQ in the "chain" of recent
changes.]
Because #define macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4.
Unlike #define macros, inline functions avoid infamous macro errors since inline functions
always evaluate every argument exactly once. In other words, invoking an inline function is
semantically just like invoking a regular function, only faster:
// A macro that returns the absolute value of i
#define unsafe(i) \
( (i) >= 0 ? (i) : -(i) )
int f();
void userCode(int x)
{
int ans;
Nope.
Beware that overuse of inline functions can cause code bloat, which can in turn have a negative
performance impact in paging environments.
The term code bloat simply means that the size of the code gets larger (bloated). In the context of
inline functions, the concern is that too many inline functions might increase the size of the
executable (i.e., cause code bloat), and that might cause the operating system to thrash, which simply
means it spends most of its time going out to disk to pull in the next chunk of code.
Of course it's also possible that inline functions will decrease the size of the executable. This may
seem backwards, but it's really true. In particular, the amount of code necessary to call a function is
sometimes greater than the amount of code to expand the function inline. This can happen with very
short functions, and it can also happen with long functions when the optimizer is able to remove a lot of
redundant code that is, when the optimizer is able to make the long function short.
So the message is this: there is no simple answer. You have to play with it to see what is best. Do not
settle for a simplistic answer like, "Never use inline functions" or "Always use inline functions" or
"Use inline functions if and only if the function is less than N lines of code." These one-size-fits-all
rules may be easy to use, but they will produce sub-optimal results.
[ Top | Bottom | Previous section | Next section ]
[15.3] How does that funky while (std::cin >> foo) syntax work?
[15.4] Why does my input seem to process past the end of file?
[15.5] Why is my program ignoring my input request after the first iteration?
[15.6] How can I provide printing for my class Fred?
[15.7] But shouldn't I always use a printOn() method rather than a friend function?
[15.8] How can I provide input for my class Fred?
[15.9] How can I provide printing for an entire hierarchy of classes?
[15.10] How can I "reopen" std::cin and std::cout in binary mode under DOS and/or OS/2?
[Recently renamed "subclassable" to "inheritable" and revamped to use new-style headers (on 7/00). Click here to go to the next
FAQ in the "chain" of recent changes.]
Increase type safety, reduce errors, improve performance, allow extensibility, and provide inheritability.
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 (using << and >>) is, relative to C (using printf()
and scanf()):
Better type safety: With <iostream>, the type of object being I/O'd is known statically by the
compiler. In contrast, <cstdio> uses "%" fields to figure out the types dynamically.
Less error prone: With <iostream>, there are no redundant "%" tokens that have to be consistent with
the actual objects being I/O'd. Removing redundancy removes a class of errors.
Extensible: The C++ <iostream> mechanism allows new user-defined types to be I/O'd without
breaking existing code. Imagine the chaos if everyone was simultaneously adding new incompatible "%"
fields to printf() and scanf()?!).
Inheritable: The C++ <iostream> mechanism is built from real classes such as std::ostream and
std::istream. Unlike <cstdio>'s FILE*, these are real classes and hence inheritable. 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.
[ Top | Bottom | Previous section | Next section ]
For example, suppose you have the following code that reads integers from std::cin:
#include <iostream>
int main()
{
std::cout << "Enter numbers separated by whitespace (use -1 to quit): ";
int i = 0;
while (i != -1) {
std::cin >> i; // BAD FORM See comments below
std::cout << "You entered " << i << '\n';
}
}
The problem with this code is that it lacks any checking to see if someone entered an invalid input character. In
particular, if someone enters something that doesn't look like an integer (such as an 'x'), the stream std::cin
goes into a "failed state," and all subsequent input attempts return immediately without doing anything. In other
words, the program enters an infinite loop; if 42 was the last number that was successfully read, the program
will print the message You entered 42 over and over.
An easy way to check for invalid input is to move the input request from the body of the while loop into the
control-expression of the while loop. E.g.,
#include <iostream>
int main()
{
std::cout << "Enter a number, or -1 to quit: ";
int i = 0;
while (std::cin >> i) { // GOOD FORM
if (i == -1) break;
[15.3] How does that funky while (std::cin >> foo) syntax work?
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of
recent changes.]
See the previous FAQ for an example of the "funky while (std::cin >> foo) syntax."
The expression (std::cin >> foo) calls the appropriate operator>> (for example, it calls the
operator>> that takes an std::istream on the left and, if foo is of type int, an int& on the right).
The std::istream operator>> functions return their left argument by convention, which in this case
means it will return std::cin. Next the compiler notices that the returned std::istream is in a boolean
context, so it converts that std::istream into a boolean.
To convert an std::istream into a boolean, the compiler calls a member function called
std::istream::operator void*(). This returns a void* pointer, which is in turn converted to a
boolean (NULL becomes false, any other pointer becomes true). So in this case the compiler generates a
call to std::cin.operator void*(), just as if you had casted it explicitly such as
(void*) std::cin.
The operator void*() cast operator returns some non-NULL pointer if the stream is in a good state, or
NULL if it's in a failed state. For example, if you read one too many times (e.g., if you're already at end-of-file),
or if the actual info on the input stream isn't valid for the type of foo (e.g., if foo is an int and the data is an
'x' character), the stream will go into a failed state and the cast operator will return NULL.
The reason operator>> doesn't simply return a bool (or void*) indicating whether it succeeded or failed
is to support the "cascading" syntax:
std::cin >> foo >> bar;
The operator>> is left-associative, which means the above is parsed as:
(std::cin >> foo) >> bar;
In other words, if we replace operator>> with a normal function name such as readFrom(), this becomes
the expression:
readFrom( readFrom(std::cin, foo), bar);
As always, we begin evaluating at the innermost expression. Because of the left-associativity of operator>>,
this happens to be the left-most expression, std::cin >> foo. This expression returns std::cin (more
precisely, it returns a reference to its left-hand argument) to the next expression. The next expression also
returns (a reference to) std::cin, but this second reference is ignored since it's the outermost expression in
this "expression statement."
[ Top | Bottom | Previous section | Next section ]
[15.4] Why does my input seem to process past the end of file?
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of
recent changes.]
Because the eof state may not get set until after a read is attempted past the end of file. That is, reading the last
byte from a file might not set the eof state. E.g., suppose the input stream is mapped to a keyboard in that
case it's not even theoretically possible for the C++ library to predict whether or not the character that the user
just typed will be the last character.
For example, the following code might have an off-by-one error with the count i:
int i = 0;
while (! std::cin.eof()) { // WRONG! (not reliable)
std::cin >> x;
++i;
// Work with x ...
}
What you really need is:
int i = 0;
while (std::cin >> x) { // RIGHT! (reliable)
++i;
// Work with x ...
}
[ Top | Bottom | Previous section | Next section ]
Because the numerical extractor leaves non-digits behind in the input buffer.
If your code looks like this:
char name[1000];
int age;
for (;;) {
#include <iostream>
class Fred {
public:
friend std::ostream& operator<< (std::ostream& o, const Fred& fred);
// ...
private:
int i_; // Just for illustration
};
int main()
{
Fred f;
std::cout << "My Fred object: " << f << "\n";
}
We use a non-member function (a friend in this case) since the Fred object is the right-hand operand of the
<< operator. If the Fred object was supposed to be on the left hand side of the << (that is,
myFred << std::cout rather than std::cout << myFred), we could have used a member function
named operator<<.
Note that operator<< returns the stream. This is so the output operations can be cascaded.
[ Top | Bottom | Previous section | Next section ]
No.
The usual reason people want to always use a printOn() method rather than a friend function is because
they wrongly believe that friends violate encapsulation and/or that friends are evil. These beliefs are naive and
wrong: when used properly, friends can actually enhance encapsulation.
This is not to say that the printOn() method approach is never useful. For example, it is useful when
providing printing for an entire hierarchy of classes. But if you use a printOn() method, it should normally
be protected, not public.
For completeness, here is "the printOn() method approach." The idea is to have a member function (often
called printOn() that does the actual printing, then have operator<< call that printOn() method.
When it is done wrongly, the printOn() method is public so operator<< doesn't have to be a friend
it can be a simple top-level function that is neither a friend nor a member of the class. Here's some sample
code:
#include <iostream>
class Fred {
public:
void printOn(std::ostream& o) const;
// ...
};
// The actual printing is done inside the printOn() method [NOT recommended!]
void Fred::printOn(std::ostream& o) const
{
// ...
}
{
fred.printOn(o);
return o;
}
People wrongly assume that this reduces maintenance cost "since it avoids having a friend function." This is a
wrong assumption because:
1. The member-called-by-top-level-function approach has zero benefit in terms of maintenance cost.
Let's say it takes N lines of code to do the actual printing. In the case of a friend function, those N lines
of code will have direct access to the class's private/protected parts, which means whenever
someone changes the class's private/protected parts, those N lines of code will need to be scanned
and possibly modified, which increases the maintenance cost. However using the printOn() method
doesn't change this at all: we still have N lines of code that have direct access to the class's
private/protected parts. Thus moving the code from a friend function into a member function
does not reduce the maintenance cost at all. Zero reduction. No benefit in maintenance cost. (If anything
it's a bit worse with the printOn() method since you now have more lines of code to maintain since
you have an extra function that you didn't have before.)
2. The member-called-by-top-level-function approach makes the class harder to use, particularly by
programmers who are not also class designers. The approach exposes a public method that
programmers are not supposed to call. When a programmer reads the public methods of the class,
they'll see two ways to do the same thing. The documentation would need to say something like, "This
does exactly the same as that, but don't use this; instead use that." And the average programmer will say,
"Huh? Why make the method public if I'm not supposed to use it?" In reality the only reason the
printOn() method is public is to avoid granting friendship status to operator<<, and that is a
notion that is somewhere between subtle and incomprehensible to a programmer who simply wants to use
the class.
Net: the member-called-by-top-level-function approach has a cost but no benefit. Therefore it is, in general, a
bad idea.
Note: if the printOn() method is protected or private, the second objection doesn't apply. There are
cases when that approach is reasonable, such as when providing printing for an entire hierarchy of classes. Note
also that when the printOn() method is non-public, operator<< needs to be a friend.
[ Top | Bottom | Previous section | Next section ]
Use operator overloading to provide a friend right-shift operator, operator>>. This is similar to the
output operator, except the parameter doesn't have a const: "Fred&" rather than "const Fred&".
#include <iostream>
class Fred {
public:
friend std::istream& operator>> (std::istream& i, Fred& fred);
// ...
private:
int i_; // Just for illustration
};
int main()
{
Fred f;
std::cout << "Enter a Fred object: ";
std::cin >> f;
// ...
}
Note that operator>> returns the stream. This is so the input operations can be cascaded and/or used in a
while loop or if statement.
[ Top | Bottom | Previous section | Next section ]
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of
recent changes.]
class Base {
public:
friend std::ostream& operator<< (std::ostream& o, const Base& b);
// ...
protected:
virtual void printOn(std::ostream& o) const;
};
The end result is that operator<< acts as if it was dynamically bound, even though it's a friend function.
This is called the Virtual Friend Function Idiom.
Note that derived classes override printOn(std::ostream&) const. In particular, they do not provide
their own operator<<.
Naturally if Base is an ABC, Base::printOn(std::ostream&) const can be declared pure
virtual using the "= 0" syntax.
[ Top | Bottom | Previous section | Next section ]
int main()
{
#if 1
std::ifstream file("../test.dat"); // RIGHT!
#else
std::ifstream file("..\test.dat"); // WRONG!
#endif
// ...
}
Remember, the backslash ("\") is used in string literals to create special characters: "\n" is a newline, "\b"
is a backspace, and "\t" is a tab, "\a" is an "alert", "\v" is a vertical-tab, etc. Therefore the file name
"\version\next\alpha\beta\test.dat" is interpreted as a bunch of very funny characters; use
"/version/next/alpha/beta/test.dat" instead, even on systems that use a "\" as the directory
separator such as DOS, Windows, OS/2, etc. This is because the library routines on these operating systems
handle "/" and "\" interchangeably.
[ Top | Bottom | Previous section | Next section ]
There are two easy ways to do this: you can use the <stdio> facilities or the <iostream> library. In
general, you should prefer the <iostream> library.
The <iostream> library allows you to convert pretty much anything to a std::string using the
following syntax (the example converts a double, but you could substitute pretty much anything that prints
using the << operator):
#include <iostream>
#include <sstream>
#include <string>
std::string convertToString(double x)
{
std::ostringstream o;
if (o << x)
return o.str();
// some sort of error handling goes here...
return "conversion error";
}
The std::ostringstream object o offers formatting facilities just like those for std::cout. You can
use manipulators and format flags to control the formatting of the result, just as you can for other std::cout.
In this example, we insert x into o via the overloaded insertion operator, <<. This invokes the iostream
formatting facilities to convert x into a std::string. The if test makes sure the conversion works correctly
it should always succeed for built-in/intrinsic types, but the if test is good style.
The expression os.str() returns the std::string that contains whatever has been inserted into stream o,
in this case the string value of x.
There are two easy ways to do this: you can use the <stdio> facilities or the <iostream> library. In
general, you should prefer the <iostream> library.
The <iostream> library allows you to convert a std::string to pretty much anything using the
following syntax (the example converts a double, but you could substitute pretty much anything that can be
read using the >> operator):
#include <iostream>
#include <sstream>
#include <string>
[35.1] Is there a TeX or LaTeX macro that fixes the spacing on "C++"?
[Recently added a new LaTeX macro thanks to Bob Kline; rewrote (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
Yes.
Here are two LaTeX macros for the word "C++". They prevent line breaks between the C and "++", and the first packs the two "+"s close to each other, the second does not. Try them both and
see which one you like best.
\newcommand{\CC}{C\nolinebreak\hspace{-.05em}\raisebox{.4ex}{\tiny\bf +}\nolinebreak\hspace{-.10em}\raisebox{.4ex}{\tiny\bf +}}
\def\CC{{C\nolinebreak[4]\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}
Here are two more LaTeX macros for the word "C++". They allow line breaks between the C and "++", which may not be desirable, but they're included here just in case.
\def\CC{C\raise.22ex\hbox{{\footnotesize +}}\raise.22ex\hbox{\footnotesize +}}
\def\CC{{C\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}
[ Top | Bottom | Previous section ]
[35.2] Are there any pretty-printers that reformat C++ source code?
[Recently added HPS Beauty (on 7/00) and fixed the URL for Artistic Style thanks to Claus Dahl; added A2PS thanks to Clark Dorman (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
In alphabetical order:
A2PS is a Unix-based pretty-printer. It is available from www.infres.enst.fr/~demaille/a2ps/
Artistic Style is a reindenter and reformatter of C++, C and Java source code. It is available from astyle.sourceforge.net/
C++2LaTeX is a LaTeX pretty printer. It is available from mirriwinni.cse.rmit.edu.au/ftp/pub/languages/C++2LaTeX-4.0.tar.gz
C-Clearly by V Communications, Inc. is a Windows program that comes with standard formatting templates and also allows you to customize your own.
www.mixsoftware.com/product/ccl.htm
GNU indent program may help. It's available at www.arceneaux.com/indent.html. You can also find an "official" GNU mirror site by looking at
Finally, you might consider lgrind which is another C++ to LaTeX translator (check for the closest mirror site of the ctan archive). The following is a grind definition for C++ (but this one
doesn't recognize some new keywords such as bool or wchar_t, and it doesn't recognize a file ending with .cpp as C++):
C++|c++|CC:\
:pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\
:cb=/*:ce=*/:ab=//:ae=$:sb=":se=\e":lb=':\
:zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\
:le=\e':tl:id=_~\::\
:kw=asm auto break case cdecl char continue default do double else\
enum extern far float for fortran goto huge if int interrupt long\
near pascal register return short signed sizeof static struct\
switch typedef union unsigned while void\
#define #else #endif #if #ifdef #ifndef #include #undef # define\
endif ifdef ifndef include undef defined #pragma\
class const delete friend inline new operator overload private\
protected public template this virtual:
[ Top | Bottom | Previous section ]
[35.3] Is there a C++-mode for GNU emacs? If so, where can I get it?
Yes, there is a C++-mode for GNU emacs.
The latest and greatest version of C++-mode (and C-mode) is implemented in the file cc-mode.el. It is an extension of Detlef and Clamen's version. A version is included with emacs.
Newer version are available from the elisp archives.
[ Top | Bottom | Previous section ]
[35.4] Where can I get OS-specific questions answered (e.g., BC++, DOS, Windows, etc)?
See one of the following:
MS-DOS issues: comp.os.msdos.programmer
To get on the mailing list: send an e-mail message with the word "SUBSCRIBE" in the Subject: line to [email protected]
To get the FAQ: ftp://ftp.netlab.cs.rpi.edu/pub/lists/owl-list-faq/drafts/owl_faq.hlp
[35.5] Why does my DOS C++ program says "Sorry: floating point code not linked"?
[Recently added a cross reference and updated to new header syntax (on 7/00). Click here to go back to the beginning of the "chain" of recent changes.]
The compiler attempts to save space in the executable by not including the float-to-string format conversion routines unless they are necessary, but sometimes it guesses wrong, and gives you
the above error message. You can fix this by (1) using <iostream> instead of <cstdio>, or (2) by including the following function somewhere in your compilation (but don't call it!):
static void dummyfloat(float *x) { float y; dummyfloat(&y); }
See the FAQ on stream I/O for more reasons to use <iostream> vs. <cstdio>.
[ Top | Bottom | Previous section ]
[35.6] Why does my BC++ Windows app crash when I'm not running the BC45 IDE?
If you're using BC++ for a Windows app, and it works OK as long as you have the BC45 IDE running, but when the BC45 IDE is shut down you get an exception during the creation of a
window, then add the following line of code to the InitMainWindow() member function of your application (YourApp::InitMainWindow()):
EnableBWCC(TRUE);
First, the best thing to do is get rid of the macro if at all possible. In fact, get rid of all macros: they're
evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4, regardless of whether the contain an if (but
they're especially evil if they contain an if).
But if you can't (or don't want to) kill the macro that contains an if, here's how to make it less evil:
Suppose the macro looks like this:
#define MYMACRO(a,b) \
if (xyzzy) asdf()
This will cause big problems if someone uses that macro in an if statement:
if (whatever)
MYMACRO(foo,bar);
else
baz;
The problem is that the else baz nests with the wrong if: the compiler sees this:
if (whatever)
if (xyzzy) asdf();
else baz;
Obviously that's a bug.
The easy solution is to require {...} everywhere, but there's another solution that I prefer even if there's a
coding standard that requires {...} everywhere (just in case someone somewhere forgets): add a
balancing else to the macro definition:
#define MYMACRO(a,b) \
if (xyzzy) asdf(); \
else
Now the compiler will see a balanced set of ifs and elses:
if (whatever)
if (xyzzy)
asdf();
else
; // that's an empty statement
else
baz;
Like I said, I personally do the above even when the coding standard calls for {...} in all the ifs. Call
me paranoid, but I sleep better at night and my code has fewer bugs.
Note: you need to make sure to put a ; at the end of the macro usage (not at the end of the macro
definition!!). For example, the macro usage should look like this:
if (whatever)
MYMACRO(foo,bar); // right: there is a ; after MYMACRO(...)
else
baz;
Note: there is another #define macro (do {...} while (false)) that is fairly popular, but that has
some strange side-effects when used in C++.
[34.2] What should be done with macros that have multiple lines?
[Recently changed "if (1)..." to "if (true)..." and "do...while (0)" to "do...while (false)" (on 7/00).
Click here to go to the next FAQ in the "chain" of recent changes.]
Answer: Choke, gag, cough. Macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4. Kill
them all!!
But if you can't (or don't want to) kill them, here's how to make them less evil:
Suppose the macro looks like this:
#define MYMACRO(a,b) \
statement1; \
statement2; \
... \
statementN;
This can cause problems if someone uses the macro in a context that demands a single statement. E.g.,
while (whatever)
MYMACRO(foo, bar);
The naive solution is to wrap the statements inside {...}, such as this:
#define MYMACRO(a,b) \
{ \
statement1; \
statement2; \
... \
statementN; \
}
But this will cause compile-time errors with things like the following:
if (whatever)
MYMACRO(foo, bar);
else
baz;
since the compiler will see a } ; else which is illegal:
if (whatever)
{
statement1;
statement2;
...
statementN;
}; // ERROR: { } cannot have a ; before an else
else
baz;
The usual solution in C was to wrap the statements inside a do { <statements go here>
} while (false), since that will execute the <statements go here> part exactly once. E.g., the
macro might look like this:
#define MYMACRO(a, b) \
do { \
statement1; \
statement2; \
... \
statementN; \
} while (false)
Note that there is no ; at the end of the macro definition. The ; gets added by the user of the macro, such
as the following:
if (whatever)
MYMACRO(foo, bar); // The ; is added here
else
baz;
This will expand to the following (note that the ; added by the user goes after (and completes) the "}
while (false)" part):
if (whatever)
do {
statement1;
statement2;
...
statementN;
} while (false);
else
baz;
The only problem with this is that it looks like a loop, and some C++ compilers refuse to "inline expand"
any method that has a loop in it.
So in C++ the best solution is to wrap the statements in an if (true) { <statements go here>
} else construct (note that the else is dangling, just like the situation described in the previous
FAQ):
#define MYMACRO(a, b) \
if (true) { \
statement1; \
statement2; \
... \
statementN; \
} else
Now the code will expand into this (note the balanced set of ifs and elses):
if (whatever)
if (true) {
statement1;
statement2;
...
statementN;
} else
; // that's a null statement
else
baz;
[ Top | Bottom | Previous section | Next section ]
[34.3] What should be done with macros that need to paste two
tokens together?
Groan. I really hate macros. Yes they're useful sometimes, and yes I use them. But I always wash my
hands afterwards. Twice. Macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4.
Okay, here we go again, desperately trying to make an inherently evil thing a little less evil.
First, the basic approach is use the ISO/ANSI C and ISO/ANSI C++ "token pasting" feature: ##. On the
surface this would look like the following:
Suppose you have a macro called "MYMACRO", and suppose you're passing a token as the parameter of
that macro, and suppose you want to concatenate that token with the token "Tmp" to create a variable
name. For example, the use of MYMACRO(Foo) would create a variable named "FooTmp" and the use
of MYMACRO(Bar) would create a variable named "BarTmp". In this case the naive approach would be
to say this:
#define MYMACRO(a) \
/*...*/ a ## Tmp /*...*/
However (and I don't remember whether the following is a workaround for some buggy compilers or
whether it's a rule in the language, but regardless it's a good idea), you are better off with a double layer
of indirection when you use ##. Basically you ought to create a special macro for "token pasting" such as
this:
#define name2(a,b) name2_hidden(a,b)
#define name2_hidden(a,b) a ## b
Then replace your use of a ## Tmp with name2(a,Tmp):
#define MYMACRO(a) \
[34.5] What are the C++ scoping rules for for loops?
[Recently because the scoping rules for for loops are no longer "new" (thanks Stan Brown), rewote the FAQ (on 7/00).
Click here to go to the next FAQ in the "chain" of recent changes.]
Yep.
The following code used to be legal, but not any more, since i's scope is now inside the for loop only:
for (int i = 0; i < 10; ++i) {
// ...
if ( /* something weird */ )
break;
// ...
}
if (i != 10) {
// We exited the loop early; handle this situation separately
// ...
}
If you're working with some old code that uses a for loop variable after the for loop, the compiler will
(hopefully!) give you wa warning or an error message such as "Variable i is not in scope".
Unfortunately there are cases when old code will compile cleanly, but will do something different the
wrong thing. For example, if the old code has a global variable i, the above code if (i != 10)
silently change in meaning from the for loop variable i under the old rule to the global variable i under
the current rule. This is not good. If you're concerned, you should check with your compiler to see if it
has some option that forces it to use the old rules with your old code.
Note: You should avoid having the same variable name in nested scopes, such as a global i and a local
i. In fact, you should avoid globals althogether whenever you can. If you abided by these coding
standards in your old code, you won't be hurt by a lot of things, including the scoping rules for for loop
variables.
Note: If your new code might get compiled with an old compiler, you might want to put {...} around the
for loop to force even old compilers to scope the loop variable to the loop. And please try to avoid the
temptation to use macros for this. Remember: macros are evil in 4 different ways: evil#1, evil#2, evil#3,
and evil#4.
#include <iostream>
int main()
{
float a = 1000.43;
float b = 1000.0;
std::cout << a - b << '\n';
}
(On one C++ implementation, this prints 0.429993)
Disclaimer: Frustration with rounding/truncation/approximation isn't really a C++ issue; it's a computer
science issue. However, people keep asking about it on comp.lang.c++, so what follows is a nominal
answer.
Answer: Floating point is an approximation. The IEEE standard for 32 bit float supports 1 bit of sign, 8
bits of exponent, and 23 bits of mantissa. Since a normalized binary-point mantissa always has the form
1.xxxxx... the leading 1 is dropped and you get effectively 24 bits of mantissa. The number 1000.43 (and
many, many others) is not exactly representable in float or double format. 1000.43 is actually represented
as the following bitpattern (the "s" shows the position of the sign bit, the "e"s show the positions of the
exponent bits, and the "m"s show the positions of the mantissa bits):
seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
01000100011110100001101110000101
The shifted mantissa is 1111101000.01101110000101 or 1000 + 7045/16384. The fractional part is
0.429992675781. With 24 bits of mantissa you only get about 1 part in 16M of precision for float. The
double type provides more precision (53 bits of mantissa).
[ Top | Bottom | Previous section | Next section ]
[34.9] How can I create two classes that both know about each
other?
Use a forward declaration.
Sometimes you must create two classes that use each other. This is called a circular dependency. For
example:
class Fred {
public:
class Barney {
public:
Fred* bar();
};
The Fred class has a member function that returns a Barney*, and the Barney class has a member
function that returns a Fred. You may inform the compiler about the existence of a class or structure by
using a "forward declaration":
class Barney;
This line must appear before the declaration of class Fred. It simply informs the compiler that the name
Barney is a class, and further it is a promise to the compiler that you will eventually supply a complete
definition of that class.
[ Top | Bottom | Previous section | Next section ]
class Barney {
Fred x; // Error: The declaration of Fred is incomplete
};
class Fred {
Barney* y;
};
One way to solve this problem is to reverse order of the classes so the "used" class is defined before the
class that uses it:
class Barney; // Okay: forward declaration
class Fred {
Barney* y; // Okay: the first can point to an object of the second
};
class Barney {
Fred x; // Okay: the second can have an object of the first
};
Note that it is never legal for each class to fully contain an object of the other class since that would
imply infinitely large objects. In other words, if an instance of Fred contains a Barney (as opposed to
a Barney*), and a Barney contains a Fred (as opposed to a Fred*), the compiler will give you an
error.
[ Top | Bottom | Previous section | Next section ]
class Barney {
public:
void method()
{
x->yabbaDabbaDo(); // Error: Fred used before it was defined
}
private:
Fred* x; // Okay: the first can point to an object of the second
};
class Fred {
public:
void yabbaDabbaDo();
private:
Barney* y;
};
One way to solve this problem is to move the offending member function into the Barney.cpp file as a
non-inline member function. Another way to solve this problem is to reverse order of the classes so
the "used" class is defined before the class that uses it:
class Barney; // Okay: forward declaration
class Fred {
public:
void yabbaDabbaDo();
private:
Barney* y; // Okay: the first can point to an object of the second
};
class Barney {
public:
void method()
{
x->yabbaDabbaDo(); // Okay: Fred is fully defined at this point
}
private:
Fred* x;
};
Just remember this: Whenever you use forward declaration, you can use only that symbol; you may not
do anything that requires knowledge of the forward-declared class. Specifically you may not access any
members of the second class.
[ Top | Bottom | Previous section | Next section ]
Because the std::vector<> template needs to know the sizeof() its contained elements, plus the
std::vector<> probably accesses members of the contained elements (such as the copy constructor,
the destructor, etc.). For example,
class Fred; // Okay: forward declaration
class Barney {
std::vector<Fred> x; // Error: the declaration of Fred is incomplete
};
class Fred {
Barney* y;
};
One solution to this problem is to change Barney so it uses a std::vector<> of Fred pointers
rather than a std::vector<> of Fred objects:
class Fred; // Okay: forward declaration
class Barney {
std::vector<Fred*> x; // Okay: Barney can use Fred pointers
};
class Fred {
Barney* y;
};
Another solution to this problem is to reverse the order of the classes so Fred is defined before
Barney:
class Barney; // Okay: forward declaration
class Fred {
Barney* y; // Okay: the first can point to an object of the second
};
class Barney {
std::vector<Fred> x; // Okay: Fred is fully defined at this point
};
Just remember this: Whenever you use a class as a template parameter, the declaration of that class must
be complete and not simply forward declared.
Your C++ compiler should direct the linking process (e.g., so it can get its special libraries)
Your C and C++ compilers probably need to come from same vendor and have compatible
versions (e.g., so they have the same calling conventions)
In addition, you'll need to read the rest of this section to find out how to make your C functions callable
by C++ and/or your C++ functions callable by C.
[ Top | Bottom | Previous section | Next section ]
[Recently added the whole section on "compiling C code with a C++ compiler," with inspiration thanks to Sebastian
Kapfer (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
To #include a standard header file (such as <cstdio>), you don't have to do anything unusual. E.g.,
int main()
{
std::printf("Hello world\n"); // Nothing unusual in the call either
}
If you consider the std:: part of the std::printf() call is unusual, then the best thing to do is "get
over it." In other words, it's the standard way to use names in the standard library, so you might as well
start getting used to it now.
However if you are compiling C code using your C++ compiler, you don't want to have to tweak all these
calls from printf() to std::printf(). Fortunately in this case the C code will use the old-style
header, <stdio.h>, rather than the new-style header, <cstdio>, and the magical of namespaces
takes care of everything else:
/* This is C code that I'm compiling using a C++ compiler */
int main()
{
printf("Hello world\n"); /* Nothing unusual in the call either */
}
Final comment: if you have C headers that are not part of the standard library, we have somewhat
different guidelines for you. There are two cases: either you can't change the header, or you can change
the header.
extern "C" {
// Get declaration for f(int i, char c, float x)
#include "my-C-code.h"
}
int main()
{
f(7, 'x', 3.14); // Note: nothing unusual in the call
}
Note: Somewhat different guidelines apply for C headers provided by the system (such as <cstdio>)
and for C headers that you can change.
int main()
{
f(7, 'x', 3.14); // Note: nothing unusual in the call
}
Note: Somewhat different guidelines apply for C headers provided by the system (such as <cstdio>)
and for C headers that you can't change.
Note: #define macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4. But they're still
// ...
{
// ...
}
The extern C line tells the compiler that the external information sent to the linker should use C
calling conventions and name mangling (e.g., preceded by a single underscore). Since name overloading
isn't supported by C, you can't make several overloaded functions simultaneously callable by a C
program.
[ Top | Bottom | Previous section | Next section ]
[29.7] Why is the linker giving errors for C/C++ functions being called
from C++/C functions?
If you didn't get your extern C right, you'll sometimes get linker errors rather than compiler errors.
This is due to the fact that C++ compilers usually "mangle" function names (e.g., to support function
overloading) differently than C compilers.
See the previous two FAQs on how to use extern C.
[ Top | Bottom | Previous section | Next section ]
#ifdef __cplusplus
class Fred {
public:
Fred();
void wilma(int);
private:
int a_;
};
#else
typedef
struct Fred
Fred;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /*FRED_H*/
Fred.cpp:
// This is C++ code
#include "Fred.h"
Fred::Fred() : a_(0) { }
void Fred::wilma(int a) { }
#include "Fred.h"
int main()
{
Fred fred;
c_function(&fred);
return 0;
}
c-function.c:
/* This is C code */
#include "Fred.h"
[29.10] Why do I feel like I'm "further from the machine" in C++ as
opposed to C?
Because you are.
As an OO programming language, C++ allows you to model the problem domain itself, which allows
you to program in the language of the problem domain rather than in the language of the solution
domain.
One of C's great strengths is the fact that it has "no hidden mechanism": what you see is what you get.
You can read a C program and "see" every clock cycle. This is not the case in C++; old line C
programmers (such as many of us once were) are often ambivalent (can you say, "hostile"?) about this
feature. However after they've made the transition to OO thinking, they often realize that although C++
hides some mechanism from the programmer, it also provides a level of abstraction and economy of
expression which lowers maintenance costs without destroying run-time performance.
Naturally you can write bad code in any language; C++ doesn't guarantee any particular level of quality,
reusability, abstraction, or any other measure of "goodness."
C++ doesn't try to make it impossible for bad programmers to write bad programs; it enables
reasonable developers to create superior software.
[ Top | Bottom | Previous section | Next section ]
[2.2] How can I get a Copy of all the HTML files of C++ FAQ Lite so I
can read them Off-Line?
Here's how you can get a bundled and compressed copy of the HTML files of C++ FAQ Lite e-mailed to
you:
1. Select a format (.zip is common on Windows and the Mac, .tar.Z and .tar.gz are common
on UNIX), then click the associated button below (but only click it once). You won't see a
confirmation page in your Web browser (although some browsers show you an e-mail window; if
so, just click "SEND"):
.zip .tar.Z .tar.gz
Restriction: the FAQ uses "long filenames." If your machine can't handle long filenames (e.g., if it's DOS
and/or Windows 3.x), you cannot unpack the FAQ. UNIX, Windows NT, Windows 95, Windows 98,
and Mac all handle long filenames correctly.
Note: e-mail was selected over FTP or HTTP.
[2.3] How can I get a Copy of all the "plaintext" files of C++ FAQ Lite
so I can read them Off-Line?
The "plaintext" version of C++ FAQ Lite is posted monthly on comp.lang.c++. These simple text
files are mechanically produced by stripping the HTML tags from the HTML files on
www.parashift.com/c++-faq-lite/. Therefore the plaintext files aren't as pretty to look at and
don't have the hyper-linked cross references, but they have basically the same information as the HTML
files.
Here's how you can get a bundled and compressed copy of the plaintext files of C++ FAQ Lite e-mailed
to you:
1. Select a format (.zip is common on Windows and the Mac, .tar.Z and .tar.gz are common
on UNIX), then click the associated button below (but only click it once). You won't see a
confirmation page in your Web browser (although some browsers show you an e-mail window; if
so, just click "SEND"):
.zip .tar.Z .tar.gz
[2.4] Why is the download via email? Why not via ftp?
Using FTP or HTTP would have a "cache coherency" problem.
Over the years I've noticed that there are a lot of out-of-date (nay, ancient) copies of C++ FAQ Lite
floating around the Internet. This has caused a lot of confusion since these ancient versions often
contained bugs, missed features, and generally outdated information. Not only has it caused confusion
for many, it has resulted in a plethora of worthless email in my inbox. I couldn't ever seem to get "over
the hump": no matter how clear I made the current version, hundreds (perhaps thousands) of people were
unaware that they were reading an outdated version. That made it harder for both them and me.
By downloading the C++ FAQ Lite via email rather than ftp, I'm able to provide an extra service for
people: the robot mailer (the Perl script that sends the FAQ copies to everyone) remembers which
version of the FAQ each person has, and when someone's version becomes out of date, the robot will
send them a courtesy email. Something like, "Your copy of the FAQ is out of date; if you want to
upgrade, click here". (Note: I haven't built this feature yet; please be patient.)
The goal is to help you keep up-to-date, so you won't end up reading outdated information. And also to
keep my inbox from getting flooded with questions from confused readers who are reading a copy of the
FAQ written before they discovered Fire.
So please please don't send me e-mail asking for an FTP address since there isn't one. Thanks!
[ Top | Bottom | Previous section | Next section ]
www.cis.nctu.edu.tw/chinese/doc/research/c++/C++FAQ-Chinese/ contains a
Chinese translation encoded in the "Big5" code. Note: "Big5" is a 16-bit Chinese code used mostly in
Taiwan.
[ Top | Bottom | Previous section | Next section ]
#if 0
{
return add(add(mul(a,b), mul(b,c)), mul(c,a)); // Yuk...
}
#else
#endif
[ Top | Bottom | Previous section | Next section ]
x = *p might dereference a "smart pointer" that actually "points" to a disk record it could
actually seek to the location on disk where p "points" and return the appropriate record into x
[ Top | Bottom | Previous section | Next section ]
inline
int& Array::operator[] (unsigned i) // Some people don't like this syntax
{
// ...
}
Some people don't like the keyword operator or the somewhat funny syntax that goes with it in the body
of the class itself. But the operator overloading syntax isn't supposed to make life easier for the
developer of a class. It's supposed to make life easier for the users of the class:
int main()
{
Array a;
a[3] = 4; // User code should be obvious and easy to understand...
}
Remember: in a reuse-oriented world, there will usually be many people who use your class, but there is
only one person who builds it (yourself); therefore you should do things that favor the many rather than the
few.
[ Top | Bottom | Previous section | Next section ]
int data[100];
};
int main()
{
Array a;
a.elem(10) = 42;
a.elem(12) += a.elem(13);
}
Now the same logic is presented with operator overloading:
class Array {
public:
int& operator[] (unsigned i) { if (i > 99) error(); return data[i]; }
private:
int data[100];
};
int main()
{
Array a;
a[10] = 42;
a[12] += a[13];
}
[ Top | Bottom | Previous section | Next section ]
No: at least one operand of any overloaded operator must be of some user-defined type (most of the
time that means a class).
But even if C++ allowed you to do this, which it doesn't, you wouldn't want to do it anyway since you
really should be using a std::string-like class rather than an array of char in the first place since
arrays are evil.
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the
"chain" of recent changes.]
inline
Matrix::Matrix(unsigned rows, unsigned cols)
: rows_ (rows),
cols_ (cols),
data_ (new double[rows * cols])
{
if (rows == 0 || cols == 0)
throw BadIndex("Matrix constructor has 0 size");
inline
Matrix::~Matrix()
{
delete[] data_;
}
inline
double& Matrix::operator() (unsigned row, unsigned col)
{
if (row >= rows_ || col >= cols_)
throw BadIndex("Matrix subscript out of bounds");
return data_[cols_*row + col];
}
inline
double Matrix::operator() (unsigned row, unsigned col) const
{
if (row >= rows_ || col >= cols_)
throw BadIndex("const Matrix subscript out of bounds");
return data_[cols_*row + col];
}
Then you can access an element of Matrix m using m(i,j) rather than m[i][j]:
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8);
// ...
}
[ Top | Bottom | Previous section | Next section ]
The array-of-array solution obviously works, but it is less flexible than the operator() approach.
Specifically, there are easy performance tuning tricks that can be done with the operator() approach
that are more difficult in the [][] approach, and therefore the [][] approach is more likely to lead to bad
First think about what the object logically represents, not how you intend to physically build it. For
example, suppose you have a Stack class that will be built by containing a LinkedList:
class Stack {
public:
// ...
private:
LinkedList list_;
};
Should the Stack have a get() method that returns the LinkedList? Or a set() method that takes a
LinkedList? Or a constructor that takes a LinkedList? Obviously the answer is No, since you should
design your interfaces from the outside-in. I.e., users of Stack objects don't care about LinkedLists;
they care about pushing and popping.
Now for another example that is a bit more subtle. Suppose class LinkedList is built using a linked list
of Node objects, where each Node object has a pointer to the next Node:
class Node { /*...*/ };
class LinkedList {
public:
// ...
private:
Node* first_;
};
Should the LinkedList class have a get() method that will let users access the first Node? Should the
Node object have a get() method that will let users follow that Node to the next Node in the chain? In
other words, what should a LinkedList look like from the outside? Is a LinkedList really a chain of
Node objects? Or is that just an implementation detail? And if it is just an implementation detail, how will
the LinkedList let users access each of the elements in the LinkedList one at a time?
One man's answer: A LinkedList is not a chain of Nodes. That may be how it is built, but that is not
what it is. What it is is a sequence of elements. Therefore the LinkedList abstraction should provide a
"LinkedListIterator" class as well, and that "LinkedListIterator" might have an operator++ to go to
the next element, and it might have a get()/set() pair to access its value stored in the Node (the value
in the Node element is solely the responsibility of the LinkedList user, which is why there is a
get()/set() pair that allows the user to freely manipulate that value).
Starting from the user's perspective, we might want our LinkedList class to support operations that
look similar to accessing an array using pointer arithmetic:
void userCode(LinkedList& a)
{
for (LinkedListIterator p = a.begin(); p != a.end(); ++p)
std::cout << *p << '\n';
}
To implement this interface, LinkedList will need a begin() method and an end() method. These
return a "LinkedListIterator" object. The "LinkedListIterator" will need a method to go forward, ++p; a
method to access the current element, *p; and a comparison operator, p != a.end().
The code follows. The key insight is that the LinkedList class does not have any methods that lets
users access the Nodes. Nodes are an implementation technique that is completely buried. The
LinkedList class could have its internals replaced with a doubly linked list, or even an array, and the
only difference would be some performance differences with the prepend(elem) and append(elem)
methods.
#include <cassert> // Poor man's exception handling
class LinkedListIterator;
class LinkedList;
class Node {
// No public members; this is a "private class"
friend LinkedListIterator; // A friend class
friend LinkedList;
Node* next_;
int elem_;
};
class LinkedListIterator {
public:
bool operator== (LinkedListIterator i) const;
bool operator!= (LinkedListIterator i) const;
void operator++ (); // Go to the next element
int& operator* (); // Access the current element
private:
LinkedListIterator(Node* p);
Node* p_;
friend LinkedList; // so LinkedList can construct a LinkedListIterator
};
class LinkedList {
public:
void append(int elem); // Adds elem after the end
void prepend(int elem); // Adds elem before the beginning
// ...
LinkedListIterator begin();
LinkedListIterator end();
// ...
private:
Node* first_;
};
Here are the methods that are obviously inlinable (probably in the same header file):
inline bool LinkedListIterator::operator== (LinkedListIterator i) const
{
return p_ == i.p_;
}
inline LinkedListIterator::LinkedListIterator(Node* p)
: p_(p)
{ }
Note: if it's a static member function of class Fred, its type is the same as if it was an ordinary
function: "int (*)(char,float)".
[ Top | Bottom | Previous section | Next section ]
pointers to functions; naturally the objects would embody the required function and probably a whole lot
more).
As a patch for existing software, use a top-level (non-member) function as a wrapper which takes an object
obtained through some other technique (held in a global, perhaps). The top-level function would apply the
desired member function against the global object.
E.g., suppose you want to call Fred::memberFunction() on interrupt:
class Fred {
public:
void memberFunction();
static void staticMemberFunction(); // A static member function can handle it
// ...
};
int main()
{
/* signal(SIGINT, Fred::memberFunction); */ // Can NOT do this
signal(SIGINT, Fred_memberFunction_wrapper); // OK
signal(SIGINT, Fred::staticMemberFunction); // Also OK
}
Note: static member functions do not require an actual object to be invoked, so
pointers-to-static-member-functions are type compatible with regular pointers-to-functions.
[ Top | Bottom | Previous section | Next section ]
[30.3] Why do I keep getting compile errors (type mismatch) when I try
to use a member function as an interrupt service routine?
This is a special case of the previous two questions, therefore read the previous two answers first.
Non-static member functions have a hidden parameter that corresponds to the this pointer. The this
pointer points to the instance data for the object. The interrupt hardware/firmware in the system is not capable
of providing the this pointer argument. You must use "normal" functions (non class members) or static
member functions as interrupt service routines.
One possible solution is to use a static member as the interrupt service routine and have that function look
somewhere to find the instance/member pair that should be called on interrupt. Thus the effect is that a
member function is invoked on an interrupt, but for technical reasons you need to call an intermediate function
first.
[30.5] How can I avoid syntax errors when calling a member function
using a pointer-to-member-function?
Two things: (1) use a typedef, and (2) use a #define macro.
Here's the way you create the typedef:
class Fred {
public:
int f(char x, float y);
int g(char x, float y);
int h(char x, float y);
int i(char x, float y);
// ...
};
}
I strongly recommend these features. In the real world, member function invocations are a lot more complex
than the simple example just given, and the difference in readability and writability is significant.
comp.lang.c++ has had to endure hundreds and hundreds of postings from confused programmers who
couldn't quite get the syntax right. Almost all these errors would have vanished had they used these features.
Note: #define macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4. But they're still useful
sometimes. But you should still feel a vague sense of shame after using them.
[ Top | Bottom | Previous section | Next section ]
Use the usual typedef and #define macro and you're 90% done.
Note: #define macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4. But they're still useful
sometimes. Feel ashamed, feel guilty, but when an evil construct like a macro improves your software, use it.
[ Top | Bottom | Previous section | Next section ]
[Recently changed the syntax to using Engine::start; and added the sixth distinction thanks to Stan Brown;
added the third similarity; added "aggregation" as another synonym; general wordsmithing (on 4/01). Click here to go to
the next FAQ in the "chain" of recent changes.]
Engine(int numCylinders);
void start(); // Starts this Engine
};
class Car {
public:
Car() : e_(8) { } // Initializes this Car with 8 cylinders
void start() { e_.start(); } // Start this Car by starting its Engine
private:
Engine e_; // Car has-a Engine
};
The "Car has-a Engine" relationship can also be expressed using private inheritance:
class Car : private Engine { // Car has-a Engine
public:
Car() : Engine(8) { } // Initializes this Car with 8 cylinders
using Engine::start; // Start this Car by starting its Engine
};
There are several similarities between these two variants:
In both cases there is exactly one Engine member object contained in every Car object
In both cases the Car class has a start() method that calls the start() method on the
contained Engine object.
There are also several distinctions:
The simple-composition variant is needed if you want to contain several Engines per Car
The private-inheritance variant allows access to the protected members of the base class
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the
"chain" of recent changes.]
Use composition when you can, private inheritance when you have to.
Normally you don't want to have access to the internals of too many other classes, and private
inheritance gives you some of this extra power (and responsibility). But private inheritance isn't evil;
it's just more expensive to maintain, since it increases the probability that someone will change
something that will break your code.
A legitimate, long-term use for private inheritance is when you want to build a class Fred that
uses code in a class Wilma, and the code from class Wilma needs to invoke member functions
from your new class, Fred. In this case, Fred calls non-virtuals in Wilma, and Wilma calls
(usually pure virtuals) in itself, which are overridden by Fred. This would be much harder to do with
composition.
class Wilma {
protected:
void fredCallsWilma()
{
std::cout << "Wilma::fredCallsWilma()\n";
wilmaCallsFred();
}
virtual void wilmaCallsFred() = 0; // A pure virtual function
};
[Recently renamed "subclass" to "derived class" (on 7/00). Click here to go to the next FAQ in the "chain" of recent
changes.]
Similarities: both allow overriding virtual functions in the private/protected base class,
neither claims the derived is a kind-of its base.
Dissimilarities: protected inheritance allows derived classes of derived classes to know about the
inheritance relationship. Thus your grand kids are effectively exposed to your implementation details.
This has both benefits (it allows derived classes of the protected derived class to exploit the
relationship to the protected base class) and costs (the protected derived class can't change the
relationship without potentially breaking further derived classes).
Protected inheritance uses the : protected syntax:
class Car : protected Engine {
public:
// ...
};
[ Top | Bottom | Previous section | Next section ]
[24.6] What are the access rules with private and protected
inheritance?
[Recently renamed "subclass" to "derived class" (on 7/00). Click here to go to the next FAQ in the "chain" of recent
changes.]
[21.2] Derived* > Base* works OK; why doesn't Derived** >
Base** work?
C++ allows a Derived* to be converted to a Base*, since a Derived object is a kind of a Base
object. However trying to convert a Derived** to a Base** is flagged as an error. Although this error
may not be obvious, it is nonetheless a good thing. For example, if you could convert a Car** to a
Vehicle**, and if you could similarly convert a NuclearSubmarine** to a Vehicle**, you
could assign those two pointers and end up making a Car* point at a NuclearSubmarine:
class Vehicle {
public:
virtual ~Vehicle() { }
virtual void startEngine() = 0;
};
int main()
{
Car car;
Car* carPtr = &car;
Car** carPtrPtr = &carPtr;
Vehicle** vehiclePtrPtr = carPtrPtr; // This is an error in C++
NuclearSubmarine sub;
NuclearSubmarine* subPtr = ⊂
*vehiclePtrPtr = subPtr;
// This last line would have caused carPtr to point to sub !
carPtr->openGasCap(); // This might call fireNuclearMissle()!
}
In other words, if it was legal to convert a Derived** to a Base**, the Base** could be
dereferenced (yielding a Base*), and the Base* could be made to point to an object of a different
derived class, which could cause serious problems for national security (who knows what would happen
if you invoked the openGasCap() member function on what you thought was a Car, but in reality it
was a NuclearSubmarine!! Try the above code out and see what it does on most compilers it will
call NuclearSubmarine::fireNuclearMissle()!
(Note: this FAQ has to do with public inheritance; private and protected inheritance are
different.)
[ Top | Bottom | Previous section | Next section ]
Nope.
This is a corollary of the previous FAQ. Unfortunately this one can get you into a lot of hot water.
Consider this:
class Base {
public:
virtual void f(); // 1
};
public:
// ...
private:
int i_; // 2
};
int main()
{
Derived arrayOfDerived[10]; // 4
userCode(arrayOfDerived); // 5
}
The compiler thinks this is perfectly type-safe. Line 5 converts a Derived* to a Base*. But in reality
it is horrendously evil: since Derived is larger than Base, the pointer arithmetic done on line 3 is
incorrect: the compiler uses sizeof(Base) when computing the address for arrayOfBase[1], yet
the array is an array of Derived, which means the address computed on line 3 (and the subsequent
invocation of member function f()) isn't even at the beginning of any object! It's smack in the middle of
a Derived object. Assuming your compiler uses the usual approach to virtual functions, this will
reinterpret the int i_ of the first Derived as if it pointed to a virtual table, it will follow that
"pointer" (which at this point means we're digging stuff out of a random memory location), and grab one
of the first few words of memory at that location and interpret them as if they were the address of a C++
member function, then load that (random memory location) into the instruction pointer and begin
grabbing machine instructions from that memory location. The chances of this crashing are very high.
The root problem is that C++ can't distinguish between a pointer-to-a-thing and a
pointer-to-an-array-of-things. Naturally C++ "inherited" this feature from C.
NOTE: If we had used an array-like class (e.g., std::vector<Derived> from the standard library)
instead of using a raw array, this problem would have been properly trapped as an error at compile time
rather than a run-time disaster.
(Note: this FAQ has to do with public inheritance; private and protected inheritance are
different.)
[ Top | Bottom | Previous section | Next section ]
Seriously, arrays are very closely related to pointers, and pointers are notoriously difficult to deal with.
But if you have a complete grasp of why the above few FAQs were a problem from a design perspective
(e.g., if you really know why a container of Thing is not a kind-of container of Anything), and if you
think everyone else who will be maintaining your code also has a full grasp on these OO design truths,
then you should feel free to use arrays. But if you're like most people, you should use a template
container class such as std::vector<T> from the standard library rather than raw arrays.
(Note: this FAQ has to do with public inheritance; private and protected inheritance are
different.)
[ Top | Bottom | Previous section | Next section ]
Derive Circle and Ellipse from a base class representing "Ellipses that can't necessarily
perform an unequal-setSize() operation"
In the first case, Ellipse could be derived from class AsymmetricShape, and setSize(x,y)
could be introduced in AsymmetricShape. However Circle could be derived from
SymmetricShape which has a setSize(size) member function.
In the second case, class Oval could only have setSize(size) which sets both the width() and
the height() to size. Ellipse and Circle could both inherit from Oval. Ellipse but not
Circle could add the setSize(x,y) operation (but beware of the hiding rule if the same member
function name setSize() is used for both operations).
(Note: this FAQ has to do with public inheritance; private and protected inheritance are
different.)
(Note: setSize(x,y) isn't sacred. Depending on your goals, it may be okay to prevent users from
changing the dimensions of an Ellipse, in which case it would be a valid design choice to not have a
setSize(x,y) method in Ellipse. However this series of FAQs discusses what to do when you
want to create a derived class of a pre-existing base class that has an "unacceptable" method in it. Of
course the ideal situation is to discover this problem when the base class doesn't yet exist. But life isn't
always ideal...)
The real problem is your intuitive notion of "kind of" doesn't match the OO notion of proper inheritance
(technically called "subtyping"). The bottom line is that the derived class objects must be substitutable
for the base class objects. In the case of Circle/Ellipse, the setSize(x,y) member function
violates this substitutability.
You have three choices: [1] remove the setSize(x,y) member function from Ellipse (thus
breaking existing code that calls the setSize(x,y) member function), [2] allow a Circle to have a
different height than width (an asymmetrical circle; hmmm), or [3] drop the inheritance relationship.
Sorry, but there simply are no other choices. Note that some people mention the option of deriving both
Circle and Ellipse from a third common base class, but that's just a variant of option [3] above.
Another way to say this is that you have to either make the base class weaker (in this case braindamage
Ellipse to the point that you can't set its width and height to different values), or make the derived
class stronger (in this case empower a Circle with the ability to be both symmetric and, ahem,
asymmetric). When neither of these is very satisfying (such as in the Circle/Ellipse case), one
normally simply removes the inheritance relationship. If the inheritance relationship simply has to exist,
you may need to remove the mutator member functions (setHeight(y), setWidth(x), and
setSize(x,y)) from the base class.
(Note: this FAQ has to do with public inheritance; private and protected inheritance are
different.)
(Note: setSize(x,y) isn't sacred. Depending on your goals, it may be okay to prevent users from
changing the dimensions of an Ellipse, in which case it would be a valid design choice to not have a
setSize(x,y) method in Ellipse. However this series of FAQs discusses what to do when you
want to create a derived class of a pre-existing base class that has an "unacceptable" method in it. Of
course the ideal situation is to discover this problem when the base class doesn't yet exist. But life isn't
always ideal...)
[ Top | Bottom | Previous section | Next section ]
If Circle is the base class and Ellipse is the derived class, then you run into a whole new set of
problems. For example, suppose Circle has a radius() method. Then Ellipse will also need to
have a radius() method, but that doesn't make much sense: what does it even mean for a (possibly
assymetric) ellipse to have a radius?
If you get over that hurdle (e.g., by having Ellipse::radius() return the average of the major and
minor axes, or whatever), then there is a problem with the relationship between radius() and
area(). E.g., suppose Circle has an area() method that promises to return 3.14159[etc] times the
square whatever radius() returns. Then either Ellipse::area() will not return the true area of
the ellipse, or you'll have to stand on your head to get radius() to return something that matches the
above formula.
Even if you get past that one (i.e., by having Ellipse::radius() return the square root of the
ellipse's area divided by pi), you'll get stuck by the circumference() method. E.g., suppose
Circle has a circumference() method that promises to return two times pi times whatever is
returned by radius(). Now you're stuck: there's no way to make all those constraints work out for
Ellipse: the Ellipse class will have to lie about its area, its circumference, or both.
Bottom line: you can make anything inherit from anything provided the methods in the derived class
abide by the promises made in the base class. But you ought not to use inheritance just because you feel
like it, or just because you want to get code reuse. You should use inheritance (a) only if the derived
class's methods can abide by all the promises made in the base class, and (b) only if you don't think you'll
confuse your users, and (c) only if there's something to be gained by using the inheritance some real,
measurable improvement in time, money or risk.
[ Top | Bottom | Previous section | Next section ]
Global changes:
Updated the opening page so it lists both the chain of recent changes as well as the table of recent
changes. This improvement is thanks to a suggestion by John Kewley.
Changed FAQs:
[5.2] How do I get other people to do my homework problem for me?
(added stuff about the evils of asking others to do your homework for you via email)
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(total rewrite; changed several URLs thanks to Brian K. Hamon and Garen Parham)
[9.7] Are inline functions guaranteed to make your performance better?
(explained "code bloat" and also added lots of if's, and's and but's)
[10.6] Should my constructors use "initialization lists" or "assignment"?
(rewrote)
[10.7] Should you use the this pointer in the constructor?
(rewrote because of a suggestion from Perry Rapp)
[10.9] Why can't I initialize my static member data in my constructor's initialization list?
(added a "," in the initialization list thanks to Yaroslav Mironov)
[14.2] Do friends violate encapsulation?
(made a bit more emphatic)
[14.4] What does it mean that "friendship isn't inherited, transitive, nor reciprocal"?
(added the "not reciprocal" item thanks to Karel Roose)
[15.7] But shouldn't I always use a printOn() method rather than a friend function?
(fixed a bug thanks to Richard Hector)
[16.16] But the previous FAQ's code is SOOOO tricky and error prone! Isn't there a simpler way?
(fixed the Star Trek movie number thanks to Chris Sheppard)
[16.16] But the previous FAQ's code is SOOOO tricky and error prone! Isn't there a simpler way?
(wordsmithed last paragraph at the suggestion of prapp)
[16.21] How do I do simple reference counting?
(moved definition of Fred::create() methods below the definition of class FredPtr)
[16.26] What are the two kinds of garbage collectors for C++?
(added a URL for Bartlett's collector thanks to Abhishek)
[17.2] How can I handle a constructor that fails?
(fixed typo ("its" vs. "it's") thanks to Wes Bemont)
[24.2] How are "private inheritance" and "composition" similar?
(changed the syntax to using Engine::start; and added the sixth distinction thanks to Stan
Brown; added the third similarity; added "aggregation" as another synonym; general
wordsmithing)
[25.1] What are some good C++ coding standards?
(fixed typo changing "where" to "were" thanks to Robert Marshall)
[25.10] Which is better: identifier names that_look_like_this or identifier names
thatLookLikeThis?
(clarified the last paragraph)
[25.11] Are there any other sources of coding standards?
(added a new URL thanks to Christopher Lott <chris "at" lott.com>; added
www.arcticlabs.com/codingstandards/ thanks to Richard)
Global changes:
Moved the main FAQ site to www.parashift.com/c++-faq-lite/. (This was
unfortunately necessary due to a business issue involving AT&T and the previous web hosting
company, Cerf-Net.)
New FAQs:
[4.2] What updates were made for the 07/00 release?
Changed FAQs:
[2.5] Where can I download a Chinese translation of this on-line document?
(updated the URL)
[3.1] Is there a C++ FAQ Book in addition to the C++ FAQ Lite?
(added BookPool.com and AllDirect.com thanks to Stan Brown, plus reorganized)
[3.2] Is there a big difference between C++ FAQ Lite and C++ FAQ Book?
(changed 'much' to 'many' thanks to Stan Brown)
[6.5] Who uses C++?
(rewrote)
[6.8] Are virtual functions (dynamic binding) central to OO/C++?
(inserted "the" before "difference" thanks to Stan Brown and reworded references to STL)
[6.11] Is C++ standardized?
(changed "has been finalized" to "was finalized" thanks to Stan Brown)
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(added URLs to free copies of CD2)
[9.3] Why should I use inline functions? Why not just use plain old #define macros?
(rewrote the sentence on #define being evil)
[10.5] Which constructor gets called when I create an array of Fred objects?
(changed so it uses new-style headers and the std:: syntax and reworded references to STL)
[10.8] What is the "Named Constructor Idiom"?
(fixed a typo (Fred vs. Point) in the prose thanks to Roy LeCates)
[12.3] OK, OK, already; I'll handle self-assignment. How do I do it?
(reworded the last paragraph)
[13.3] What are some examples of operator overloading?
(changed so it uses the std:: syntax)
[13.6] Can I overload operator== so it lets me compare two char[] using a string
comparison?
(changed so it uses the std:: syntax)
[13.8] How do I create a subscript operator for a Matrix class?
(changed so it uses new-style headers and the std:: syntax)
[13.10] Should I design my classes from the outside (interfaces first) or from the inside (data
first)?
(changed so it uses new-style headers and the std:: syntax and reworded references to STL)
[15.1] Why should I use <iostream> instead of the traditional <cstdio>?
(renamed "subclassable" to "inheritable" and revamped to use new-style headers)
[15.2] Why does my program go into an infinite loop when someone enters an invalid input
character?
(changed so it uses new-style headers and the std:: syntax)
[15.3] How does that funky while (std::cin >> foo) syntax work?
(changed so it uses new-style headers and the std:: syntax)
[15.4] Why does my input seem to process past the end of file?
(changed so it uses new-style headers and the std:: syntax)
[15.5] Why is my program ignoring my input request after the first iteration?
(changed so it uses new-style headers and the std:: syntax)
[15.6] How can I provide printing for my class Fred?
(changed so it uses new-style headers and the std:: syntax)
[15.8] How can I provide input for my class Fred?
(changed so it uses new-style headers and the std:: syntax)
[15.9] How can I provide printing for an entire hierarchy of classes?
(changed so it uses new-style headers and the std:: syntax)
[15.10] How can I "reopen" std::cin and std::cout in binary mode under DOS and/or
OS/2?
(changed so it uses new-style headers and the std:: syntax)
[15.11] Why can't I open a file in a different directory such as "..\test.dat"?
(changed so it uses new-style headers and uses the std:: syntax)
[16.5] Do I need to check for NULL after p = new Fred()?
(changed so it uses new-style headers and the std:: syntax)
[16.6] How can I convince my (older) compiler to automatically check new to see if it returns
NULL?
(changed the example to use throw rather than abort() thanks to Stan Brown; changed to use
new-style headers and the std:: syntax)
[16.13] After p = new Fred[n], how does the compiler know there are n objects to be
destructed during delete[] p?
(changed "popluar" to "popular" thanks to Fabrice Clerc)
[16.15] How do I allocate multidimensional arrays using new?
(fixed a leak in the third manipulateArray() by moving another for loop into the try
block)
[16.16] But the previous FAQ's code is SOOOO tricky and error prone! Isn't there a simpler way?
(clarified the last paragraph)
[16.17] But the above Matrix class is specific to Fred! Isn't there a way to make it generic?
(rewrote)
[16.19] Does C++ have arrays whose length can be specified at run-time?
(changed so it uses new-style headers and the std:: syntax and reworded references to STL)
[16.22] How do I provide reference counting with copy-on-write semantics?
(rewrote the first paragraph for clarity thanks to Fabrice Clerc)
[16.23] How do I provide reference counting with copy-on-write semantics for a hierarchy of
classes?
(changed so it uses new-style headers and the std:: syntax)
[17.5] How do I change the string-length of an array of char to prevent memory leaks even
if/when someone throws an exception?
(rewrote the last half)
[18.1] What is "const correctness"?
(changed so it uses new-style headers and the std:: syntax)
[18.2] How is "const correctness" related to ordinary type safety?
(changed so it uses new-style headers and the std:: syntax)
[18.9] What is a "const member function"?
(removed a spurious ")" thanks to Stan Brown)
[18.12] Why does the compiler allow me to change an int after I've pointed at it with a
const int*?
(changed so it uses new-style headers and the std:: syntax)
[19.3] How do you express inheritance in C++?
(added "derived class of" to the list of synonyms)
[19.7] How can I protect derived classes from breaking when I change internal parts?
(renamed "subclass" to "derived class")
[21.4] Is an array of Derived a kind-of array of Base?
(changed so it uses new-style headers and the std:: syntax and reworded references to STL)
Changed FAQs:
[2.6] Where can I download a Portuguese translation of this on-line document?
(updated the URL for the Portuguese translation of the FAQ thanks to Ricardo F. de Oliveira)
[3.1] Is there a C++ FAQ Book in addition to the C++ FAQ Lite?
(rewrote)
[3.2] Is there a big difference between C++ FAQ Lite and C++ FAQ Book?
(rewrote)
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(changed the URL for the electronic copy of the Standard thanks to Wolfgang Haefelinger)
[9.3] Why should I use inline functions? Why not just use plain old #define macros?
(added cross references to other evilness of macros)
[11.8] What if I can't wrap the local in an artificial block?
(added the note about constructors at the end)
[13.10] Should I design my classes from the outside (interfaces first) or from the inside (data
first)?
(added friend relationship between LinkedListIterator and LinkedList thanks to
Mnica Garca Garca; reworded "In the case of OO software..." sentence thanks to Fabrice Clerc)
[18.10] What do I do if I want to update an "invisible" data member inside a const member
function?
(added a warning against use of const_cast on const objects thanks to TiTi)
[20.5] What is a "virtual constructor"?
(added the paragraph on Covariant Return Types)
[27.3] Which is a better fit for C++: "static typing" or "dynamic typing"?
(added cross references to evilness of macros)
[29.4] How can I modify my own C header files so it's easier to #include them in C++ code?
(added the "macros are sometimes useful" paragraph at the end)
[30.1] Is the type of "pointer-to-member-function" different from "pointer-to-function"?
(changed another "It's" to "Its" thanks to Chris Young)
[30.5] How can I avoid syntax errors when calling a member function using a
pointer-to-member-function?
(added the "macros are sometimes useful" paragraph at the end)
[30.6] How do I create and use an array of pointers to member functions?
(added the "macros are sometimes useful" paragraph at the end)
[ Top | Bottom | Previous section | Next section ]
Changed FAQs:
[2.1] Where's the closest mirror site to access this document?
(changed the rationale for choosing a close site thanks to Stan Brown)
[2.4] Why is the download via email? Why not via ftp?
(added caveat that out-of-date reminders aren't implemented yet thanks to Stan Brown)
[5.1] What does IMHO mean? (or IMO, IMNSHO, FWIW, OTOH, etc.)?
(added IMAO thanks to Charles R Martin)
[5.9] How do I get the FAQs for a particular newsgroup?
(added www.faqs.org thanks to Dan Kegel)
[6.8] Are virtual functions (dynamic binding) central to OO/C++?
(reworded the second paragraph thanks to Stan Brown)
[6.11] Is C++ standardized?
(changed "American National Standards Organization" to "American National Standards Institute"
thanks to Mark Jones; also reworded first paragraph thanks to Stan Brown)
[12.1] What is "self assignment"?
(changed "knowning" to "knowing" thanks to Stan Brown)
[12.3] OK, OK, already; I'll handle self-assignment. How do I do it?
(reworded the last paragraph thanks to Stan Brown)
[13.5] What operators can/cannot be overloaded?
(got rid of #if/#else/#endif by splitting the example thanks to Stan Brown)
[15.11] Why can't I open a file in a different directory such as "..\test.dat"?
(added an explanation that the library routines treat "/" and "\" interchangeably thanks to Stan
Brown)
[18.13] Does "const Fred* p" mean that *p can't change?
(added an indication that there might be other non-const ways to get at the object thanks to Stan
Brown)
[20.2] How can C++ achieve dynamic binding yet also static typing?
(added the definition of polymorphism thanks to Kemberli Jennings)
[22.5] How do you define a copy constructor or assignment operator for a class that contains a
Changed FAQs:
[6.11] Is C++ standardized?
(changed "International Standards Organization" to "International Organization for
Standardization" thanks to [email protected])
[7.1] What is a class?
Changed FAQs:
[1.6] C++-FAQ-Lite != C++-FAQ-Book
(updated due to the Second Edition of the book)
[2.1] Where's the closest mirror site to access this document?
(added Ireland mirror site: snet.wit.ie/GreenSpirit/c++-faq-lite)
[2.2] How can I get a Copy of all the HTML files of C++ FAQ Lite so I can read them Off-Line?
(added "Windows 98" to last paragraph)
[3.1] Is there a C++ FAQ Book in addition to the C++ FAQ Lite?
(updated due to the Second Edition of the book)
[6.5] Who uses C++?
(corrected the growth rate)
[6.8] Are virtual functions (dynamic binding) central to OO/C++?
(added STL and generic programming)
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(added new ways to get a copy via the web)
[12.3] OK, OK, already; I'll handle self-assignment. How do I do it?
(tightened the wording of the last paragraph thanks to Andy Glew)
[15.3] How does that funky while (std::cin >> foo) syntax work?
(corrected a serious bug: changed operator bool() to operator void*(); thanks to
Rajinikanth Sivalingam)
[16.23] How do I provide reference counting with copy-on-write semantics for a hierarchy of
classes?
(fixed a bug by making Fred a friend of Fred::Data)
[18.9] What is a "const member function"?
(changed "const pointer" to "pointer-to-const" thanks to Saieb Khalil)
[20.4] When should my destructor be virtual?
(changed "explicit destructor" to "explicitly defined destructor" to avoid confusion with the
explicit keyword used with constructors)
[23.4] Should a derived class replace ("override") a non-virtual function from a base class?
(reworded first full paragraph)
[25.11] Are there any other sources of coding standards?
(removed the URL for the anti-guide (thanks to Bill Seymour for letting me know that the
anti-guide disappeared))
[26.5] What are some best-of-breed C++ morality guides?
(updated info on C++ FAQs book because of its Second Edition)
[26.6] What are some best-of-breed C++ legality guides?
(fixed the ISBN for Bjarne Stroustrup's book)
[28.1] What is value and/or reference semantics, and which is best in C++?
(wordsmithing changes thanks to Lance Ware)
[31.4] How can I insert/access/change elements from a linked list/hashtable/etc?
(reworded item #3 thanks to John Millaway)
[32.3] How can I find a Fred object in an STL container of Fred* such as
std::vector<Fred*>?
(fixed a typo in the code thanks to Scott Maxwell and Bill Sloan)
[33.4] How can I decompile an executable program back into C++ source code?
(wordsmithing changes thanks to Lance Ware)
[33.5] Where can I get information about the C++ compiler from {Borland, IBM, Microsoft,
Symantec, Sun, etc.}?
(corrected the URL for KAI C++ and added Rational APEX C/C++ thanks to Kevin Broadey;
corrected the URL for Borland C++ FAQ thanks to Kent Reisdorph and Michael J. Reeves)
[34.5] What are the C++ scoping rules for for loops?
(wordsmithing changes thanks to Lance Ware)
Changed FAQs:
[32.9] Where can I get tons and tons of more information on C++ class libraries?
(fixed the URL)
[ Top | Bottom | Previous section | Next section ]
[2.4] Why is the download via email? Why not via ftp?
[2.6] Where can I download a Portuguese translation of this on-line document?
[4.8] What updates were made for the 05/98 release?
[10.6] Should my constructors use "initialization lists" or "assignment"?
[33.2] Where can I get more information on using MFC and Visual C++?
Changed FAQs:
[2.2] How can I get a Copy of all the HTML files of C++ FAQ Lite so I can read them Off-Line?
(made it clearer why there is no FTP or HTTP address for downloading the FAQ)
[2.3] How can I get a Copy of all the "plaintext" files of C++ FAQ Lite so I can read them
Off-Line?
(made it clearer why there is no FTP or HTTP address for downloading the FAQ)
[6.11] Is C++ standardized?
(rewrote now that the standard is here)
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(rewrote now that the standard is here)
[16.17] But the above Matrix class is specific to Fred! Isn't there a way to make it generic?
(fixed Matrix's ctor thanks to Dhavide Aruliah)
[16.22] How do I provide reference counting with copy-on-write semantics?
(fixed Fred's default ctor thanks to Scott Harris)
[32.3] How can I find a Fred object in an STL container of Fred* such as
std::vector<Fred*>?
(changed operator==() to operator()() thanks to Ali Tajeldin)
[32.4] Where can I get help on how to use STL?
(added the URL for the STL FAQ)
[33.5] Where can I get information about the C++ compiler from {Borland, IBM, Microsoft,
Symantec, Sun, etc.}?
(corrected the URL for Borland C++ & HP C++; added GNU C++, Intel Reference C++, KAI
C++, and Portland Group C++)
[35.2] Are there any pretty-printers that reformat C++ source code?
(added a URL for "GNU indent")
[ Top | Bottom | Previous section | Next section ]
[33.5] Where can I get information about the C++ compiler from {Borland, IBM, Microsoft,
Symantec, Sun, etc.}?
(corrected the URL for Microsoft Visual C++ thanks to Leila Rannanjarvi, and added the URL for
Sun C++ thanks to Aryan Mirsepassi)
[35.2] Are there any pretty-printers that reformat C++ source code?
(added information about tgrind)
[ Top | Bottom | Previous section | Next section ]
New FAQs:
[4.10] What updates were made for the 01/97 release?
[15.2] Why does my program go into an infinite loop when someone enters an invalid input
character?
[15.3] How does that funky while (std::cin >> foo) syntax work?
[16.16] But the previous FAQ's code is SOOOO tricky and error prone! Isn't there a simpler way?
[25.5] Is the ?: operator evil since it can be used to create unreadable code?
Changed FAQs:
[1.3] Copying Permissions
(simplified)
[2.1] Where's the closest mirror site to access this document?
(removed the "USA-2" site)
[2.2] How can I get a Copy of all the HTML files of C++ FAQ Lite so I can read them Off-Line?
(rewrote and added a one-click feature to get .zip, .tar.Z or .tar.gz format)
[2.3] How can I get a Copy of all the "plaintext" files of C++ FAQ Lite so I can read them
Off-Line?
(rewrote and added a one-click feature to get .zip, .tar.Z or .tar.gz format)
[5.1] What does IMHO mean? (or IMO, IMNSHO, FWIW, OTOH, etc.)?
[20.3] What's the difference between how virtual and non-virtual member functions are
called?
[33.3] How do I display text in the status bar using MFC?
(with the help of Paul Ganney)
Changed FAQs:
[8.5] How can you reseat a reference to make it refer to a different object?
(changed last line from "pointer to const" to "const pointer" thanks to Neelesh Pandit)
[25.11] Are there any other sources of coding standards?
(rewrote and added more URLs)
[33.8] If name mangling was standardized, could I link code compiled with compilers from
different compiler vendors?
(reworded and added v-table and v-pointer references)
Changed FAQs:
[5.8] Which newsgroup should I post my questions?
(added comp.sys.mac.programmer.* and comp.sys.mac.oop.*)
[16.6] How can I convince my (older) compiler to automatically check new to see if it returns
NULL?
(added comments on constructors of globals; thanks to William Carroll)
[25.11] Are there any other sources of coding standards?
(added URLs)
[33.5] Where can I get information about the C++ compiler from {Borland, IBM, Microsoft,
Symantec, Sun, etc.}?
(added URL for Metrowerks and Watcom compilers)
[ Top | Bottom | Previous section | Next section ]
[5.1] What does IMHO mean? (or IMO, IMNSHO, FWIW, OTOH, etc.)?
Changed FAQs:
[8.5] How can you reseat a reference to make it refer to a different object?
(added a cross reference regarding pointer to const)
[9.4] How do you tell the compiler to make a non-member function inline?
(strengthened the "Note:" at the end)
[16.20] How can I force objects of my class to always be created via new rather than as locals or
global/static objects?
(reworded and added a paragraph on using friend to soften the original goal)
[16.22] How do I provide reference counting with copy-on-write semantics?
(added links to the self assignment discussion)
[16.23] How do I provide reference counting with copy-on-write semantics for a hierarchy of
classes?
(added links to the self assignment discussion)
[17.4] How should I handle resources if my constructors may throw exceptions?
(added cross-references for reference-counted and remote smart-pointers)
[21.2] Derived* > Base* works OK; why doesn't Derived** > Base** work?
(fixed a bug with help from William Wu)
[22.4] What is a "pure virtual" member function?
(reworded)
[32.4] Where can I get help on how to use STL?
(fixed the URL for Kenny Zalewski's STL guide)
[33.5] Where can I get information about the C++ compiler from {Borland, IBM, Microsoft,
Symantec, Sun, etc.}?
New FAQs:
[4.14] What updates were made for the 08/96 release?
Changed FAQs:
[6.4] Is C++ better than Ada? (or Visual Basic, C, FORTRAN, Pascal, Smalltalk, or any other
language?)
(reworded the last paragraph)
[6.6] How long does it take to learn OO/C++?
(added management-level hints for training developers in OO/C++)
[9.3] Why should I use inline functions? Why not just use plain old #define macros?
(moved)
[13.4] But operator overloading makes my class look ugly; isn't it supposed to make my code
clearer?
(rewritten)
[13.8] How do I create a subscript operator for a Matrix class?
(fixed a bug: "double** data_" is now "double* data_")
[25.9] Are there any lint-like guidelines for C++?
(added links to the self assignment discussion)
[26.6] What are some best-of-breed C++ legality guides?
(fixed the ISBN for Stan Lippman's book)
[27.1] What's the difference between C++ and Smalltalk?
(rewritten)
[32.5] How can you tell if you have a dynamically typed C++ class library?
(moved from the section on Smalltalk)
[32.6] What is the NIHCL? Where can I get it?
(moved from the section on Smalltalk)
[32.9] Where can I get tons and tons of more information on C++ class libraries?
(updated the URL)
[34.4] Why can't the compiler find my header file in #include "c:\test.hpp" ?
(updated to refer to [15.11])
New FAQs:
[4.15] What updates were made for the 07/96 release?
[5.5] What do I do if someone else posts a question that's already in the FAQ?
[5.6] What makes a good Subject: line?
[6.8] Are virtual functions (dynamic binding) central to OO/C++?
[6.9] I'm from Missouri. Can you give me a simple reason why virtual functions (dynamic
binding) make a big difference?
[7.6] How can I prevent other programmers from violating encapsulation by seeing the private
parts of my class?
[7.7] Is Encapsulation a Security device?
[10.4] Is the default constructor for Fred always Fred::Fred()?
[10.5] Which constructor gets called when I create an array of Fred objects?
[10.8] What is the "Named Constructor Idiom"?
[10.9] Why can't I initialize my static member data in my constructor's initialization list?
[11.2] What's the order that local objects are destructed?
[11.3] What's the order that objects in an array are destructed?
[11.4] Can I overload the destructor for my class?
[11.5] Should I explicitly call a destructor on a local variable?
[11.6] What if I want a local to "die" before the close } of the scope in which it was created? Can I
call a destructor on a local if I really want to?
[11.7] OK, OK already; I won't explicitly call the destructor of a local; but how do I handle the
above situation?
[11.8] What if I can't wrap the local in an artificial block?
[11.9] But can I explicitly call a destructor if I've allocated my object with new?
[11.10] What is "placement new" and why would I use it?
[11.11] When I write a destructor, do I need to explicitly call the destructors for my member
objects?
[13.6] Can I overload operator== so it lets me compare two char[] using a string
comparison?
[13.8] How do I create a subscript operator for a Matrix class?
[13.10] Should I design my classes from the outside (interfaces first) or from the inside (data
first)?
[15.8] How can I provide input for my class Fred?
[16.5] Do I need to check for NULL after p = new Fred()?
[16.6] How can I convince my (older) compiler to automatically check new to see if it returns
NULL?
[16.7] Do I need to check for NULL before delete p?
[16.8] What are the two steps that happen when I say delete p?
[16.9] In p = new Fred(), does the Fred memory "leak" if the Fred constructor throws an
exception?
[16.12] Can I drop the [] when deleteing array of some built-in type (char, int, etc)?
[16.13] After p = new Fred[n], how does the compiler know there are n objects to be
destructed during delete[] p?
[16.21] How do I do simple reference counting?
[16.22] How do I provide reference counting with copy-on-write semantics?
[16.23] How do I provide reference counting with copy-on-write semantics for a hierarchy of
classes?
[17.5] How do I change the string-length of an array of char to prevent memory leaks even
if/when someone throws an exception?
[18.12] Why does the compiler allow me to change an int after I've pointed at it with a
const int*?
[22.5] How do you define a copy constructor or assignment operator for a class that contains a
pointer to a (abstract) base class?
[23.6] What does it mean that the "virtual table" is an unresolved external?
[25.10] Which is better: identifier names that_look_like_this or identifier names
thatLookLikeThis?
(with the help of James Robinson)
[29.1] What do I need to know when mixing C and C++ code?
[30.5] How can I avoid syntax errors when calling a member function using a
pointer-to-member-function?
[31.2] How can I make a perl-like associative array in C++?
[32.3] How can I find a Fred object in an STL container of Fred* such as
std::vector<Fred*>?
[32.9] Where can I get tons and tons of more information on C++ class libraries?
[33.6] How do compilers use "over-allocation" to remember the number of elements in an
allocated array?
[33.7] How do compilers use an "associative array" to remember the number of elements in an
allocated array?
[34.4] Why can't the compiler find my header file in #include "c:\test.hpp" ?
[34.5] What are the C++ scoping rules for for loops?
Changed FAQs:
[5.4] How can I find out about general netiquette so I don't embarrass myself?
(rewritten)
[5.7] How do I post a question about code that doesn't work correctly?
(rewritten)
[7.8] What's the difference between the keywords struct and class?
(rewritten)
[10.10] Why are classes with static data members getting linker errors?
(rewritten)
[11.12] When I write a derived class's destructor, do I need to explicitly call the destructor for my
base class?
(added example code to illustrate the compiler's automagic calls to destructors of member objects
and base class subobjects)
[15.6] How can I provide printing for my class Fred?
(added example code to illustrate operator<< on an ostream)
[15.9] How can I provide printing for an entire hierarchy of classes?
(moved from the section on Abstraction)
[16.20] How can I force objects of my class to always be created via new rather than as locals or
global/static objects?
(added a reference to the Named Constructor Idiom)
[29.2] How can I include a standard C header file in my C++ code?
(rewritten)
[29.3] How can I include a non-system C header file in my C++ code?
(rewritten)
[29.4] How can I modify my own C header files so it's easier to #include them in C++ code?
(rewritten)
[33.10] Is there a yacc-able C++ grammar?
(updated the URL for the yacc-able C++ grammar)
[35.2] Are there any pretty-printers that reformat C++ source code?
(added "C-Clearly" and GNU indent to the list of pretty-printers)
[ Top | Bottom | Previous section | Next section ]
Changed FAQs:
[2.1] Where's the closest mirror site to access this document?
(added Finland mirror site: www.utu.fi/~sisasa/oasis/cppfaq/)
[3.1] Is there a C++ FAQ Book in addition to the C++ FAQ Lite?
(fixed URL of book at Addison-Wesley)
[18.1] What is "const correctness"?
(added info on what happens when you try to pass a const parameter to a non-const function)
[20.4] When should my destructor be virtual?
(added the nitty-gritty rule for when you need to have a virtual destructor)
[21.4] Is an array of Derived a kind-of array of Base?
(fixed bug in code)
[22.3] What is an ABC?
(reworded)
[22.4] What is a "pure virtual" member function?
(reworded)
[28.4] Should I normally use pointers to freestore allocated objects for my data members, or
should I use "composition"?
(reworded)
[29.8] How can I pass an object of a C++ class to/from a C function?
(fixed a bug in the code)
[31.5] What's the idea behind templates?
(reworded)
[31.6] What's the syntax / semantics for a "class template"?
(reworded)
[35.1] Is there a TeX or LaTeX macro that fixes the spacing on "C++"?
(added a new LaTeX macro)
[35.2] Are there any pretty-printers that reformat C++ source code?
(fixed URL of C++2LaTeX)
[ Top | Bottom | Previous section | Next section ]
[6.4] Is C++ better than Ada? (or Visual Basic, C, FORTRAN, Pascal, Smalltalk, or any other
language?)
Changed FAQs:
[2.3] How can I get a Copy of all the "plaintext" files of C++ FAQ Lite so I can read them
Off-Line?
(added URL ftp://rtfm.mit.edu/pub/usenet-by-group/comp.lang.c++/)
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(fixed the URL for the ANSI/ISO C++ Committee Draft)
[15.1] Why should I use <iostream> instead of the traditional <cstdio>?
(reworded)
[16.2] Can I free() pointers allocated with new? Can I delete pointers allocated with
malloc()?
(added an admonition not to mix new and free() or malloc() and delete)
[25.1] What are some good C++ coding standards?
(reworded)
[25.2] Are coding standards necessary? Are they sufficient?
(reworded)
[25.3] Should our organization determine coding standards from our C experience?
(reworded)
[25.9] Are there any lint-like guidelines for C++?
(reworded)
[27.3] Which is a better fit for C++: "static typing" or "dynamic typing"?
(updated info on dynamic_cast and typeid())
[35.2] Are there any pretty-printers that reformat C++ source code?
(fixed URL of C++2LaTeX)
[ Top | Bottom | Previous section | Next section ]
[15.10] How can I "reopen" std::cin and std::cout in binary mode under DOS and/or
OS/2?
[32.4] Where can I get help on how to use STL?
[32.7] Where can I ftp the code that accompanies "Numerical Recipes"?
[32.8] Why is my executable so large?
Changed FAQs:
Changed FAQs:
[6.12] Where can I get a copy of the ANSI/ISO C++ standard?
(fixed the US-Mail access for the ANSI/ISO C++ Committee Draft)
[16.20] How can I force objects of my class to always be created via new rather than as locals or
global/static objects?
(rewritten)
[ Top | Bottom | Previous section | Next section ]
[35.4] Where can I get OS-specific questions answered (e.g., BC++, DOS, Windows, etc)?
Changed FAQs:
[32.6] What is the NIHCL? Where can I get it?
(fixed the FTP address)
[ Top | Bottom | Previous section | Next section ]
[15.4] Why does my input seem to process past the end of file?
[15.5] Why is my program ignoring my input request after the first iteration?
[16.14] Is it legal (and moral) for a member function to say delete this?
Changed FAQs:
[35.3] Is there a C++-mode for GNU emacs? If so, where can I get it?
(updated the information on cc-mode.el)
[ Top | Bottom | Previous section | Next section ]
Changed FAQs:
[24.3] Which should I prefer: composition or private inheritance?
(reworded)
[ Top | Bottom | Previous section | Next section ]
[3.2] Is there a big difference between C++ FAQ Lite and C++ FAQ Book?
[4.26] What updates were made for the 11/94 release?
[18.10] What do I do if I want to update an "invisible" data member inside a const member
function?
[27.3] Which is a better fit for C++: "static typing" or "dynamic typing"?
[8] References
(Part of C++ FAQ Lite, Copyright 1991-2001, Marshall Cline,
[email protected])
int main()
{
int x, y;
// ...
swap(x,y);
}
Here i and j are aliases for main's x and y respectively. In other words, i is x not a pointer to x, nor
a copy of x, but x itself. Anything you do to i gets done to x, and vice versa.
OK. That's how you should think of references as a programmer. Now, at the risk of confusing you by
giving you a different perspective, here's how references are implemented. Underneath it all, a reference
i to object x is typically the machine address of the object x. But when the programmer says i++, the
compiler generates code that increments x. In particular, the address bits that the compiler uses to find x
are not changed. A C programmer will think of this as if you used the C style pass-by-pointer, with the
syntactic variant of (1) moving the & from the caller into the callee, and (2) eliminating the *s. In other
words, a C programmer will think of i as a macro for (*p), where p is a pointer to x (e.g., the compiler
automatically dereferences the underlying pointer; i++ is changed to (*p)++; i = 7 is automatically
changed to *p = 7).
Important note: Even though a reference is often implemented using an address in the underlying
assembly language, please do not think of a reference as a funny looking pointer to an object. A reference
is the object. It is not a pointer to the object, nor a copy of the object. It is the object.
[ Top | Bottom | Previous section | Next section ]
int main()
{
Array a;
for (int i = 0; i < a.size(); ++i)
a[i] = 7; // This line invokes Array::operator[](int)
}
[ Top | Bottom | Previous section | Next section ]
It chains these method calls, which is why this is called method chaining.
The first thing that gets executed is object.method1(). This returns some object, which might be a
reference to object (i.e., method1() might end with return *this;), or it might be some other
object. Let's call the returned object objectB). Then objectB) becomes the this object of
method2().
The most common use of method chaining is in the iostream library. E.g., cout << x << y works
because cout << x is a function that returns cout.
A less common, but still rather slick, use for method chaining is in the Named Parameter Idiom.
[8.6] When should I use references, and when should I use pointers?
Use references when you can, and pointers when you have to.
References are usually preferred over pointers whenever you don't need "reseating". This usually means
that references are most useful in a class's public interface. References 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 pointer).
Note: Old line C programmers sometimes don't like references since they provide reference semantics
that isn't explicit in the caller's code. After some C++ experience, however, one quickly realizes this is a
form of information hiding, which is an asset rather than a liability. E.g., programmers should write code
in the language of the problem rather than the language of the machine.
[ Top | Bottom | Previous section | Next section ]
The term handle is used to mean any technique that lets you get to another object a generalized
pseudo-pointer. The term is (intentionally) ambiguous and vague.
Ambiguity is actually an asset in certain cases. For example, during early design you might not be ready
to commit to a specific representation for the handles. You might not be sure whether you'll want simple
pointers vs. references vs. pointers-to-pointers vs. pointers-to-references vs. integer indices into an array
vs. strings (or other key) that can be looked up in a hash-table (or other data structure) vs. database keys
vs. some other technique. If you merely know that you'll need some sort of thingy that will uniquely
identify and get to an object, you call the thingy a Handle.
So if your ultimate goal is to enable a glop of code to uniquely identify/look-up a specific object of some
class Fred, you need to pass a Fred handle into that glop of code. The handle might be a string that can
be used as a key in some well-known lookup table (e.g., a key in a
std::map<std::string,Fred> or a std::map<std::string,Fred*>), or it might be an
integer that would be an index into some well-known array (e.g.,
Fred* array = new Fred[maxNumFreds]), or it might be a simple Fred*, or it might be
something else.
Novices often think in terms of pointers, but in reality there are downside risks to using raw pointers.
E.g., what if the Fred object needs to move? How do we know when it's safe to delete the Fred
objects? What if the Fred object needs to (temporarily) get serialized on disk? etc., etc. Most of the time
we add more layers of indirection to manage situations like these. For example, the handles might be
Fred**, where the pointed-to Fred* pointers are guaranteed to never move but when the Fred
objects need to move, you just update the pointed-to Fred* pointers. Or you make the handle an integer
then have the Fred objects (or pointers to the Fred objects) looked up in a table/array/whatever. Or
whatever.
The point is that we use the word Handle when we don't yet know the details of what we're going to do.
Another time we use the word Handle is when we want to be vague about what we've already done
(sometimes the term magic cookie is used for this as well, as in, "The software passes around a magic
cookie that is used to uniquely identify and locate the appropriate Fred object"). The reason we
(sometimes) want to be vague about what we've already done is to minimize the ripple effect if/when the
specific details/representation of the handle change. E.g., if/when someone changes the handle from a
string that is used in a lookup table to an integer that is looked up in an array, we don't want to go and
update a zillion lines of code.
To further ease maintenance if/when the details/representation of a handle changes (or to generally make
the code easier to read/write), we often encapsulate the handle in a class. This class often overloads
operators operator-> and operator* (since the handle acts like a pointer, it might as well look like
a pointer).
[ Top | Bottom | Previous section | Next section ]
Note: Many new C++ programmers come from a Smalltalk background. If that's you, this section will
tell you the most important things you need know to make your transition. Please don't get the notion that
either language is somehow "inferior" or "bad", or that this section is promoting one language over the
other (I am not a language bigot; I serve on both the ANSI C++ and ANSI Smalltalk standardization
committees). Instead, this section is designed to help you understand (and embrace!) the differences.
If you want to use C++ most effectively, use it as a statically typed language.
C++ is flexible enough that you can (via pointer casts, unions, and #define macros) make it "look" like
Smalltalk. But don't. Which reminds me: try to avoid #define: it is evil in 4 different ways: evil#1,
evil#2, evil#3, and evil#4.
There are places where pointer casts and unions are necessary and even wholesome, but they should be
used carefully and sparingly. A pointer cast tells the compiler to believe you. An incorrect pointer cast
might corrupt your heap, scribble into memory owned by other objects, call nonexistent member
functions, and cause general failures. It's not a pretty sight. If you avoid these and related constructs, you
can make your C++ code both safer and faster, since anything that can be checked at compile time is
something that doesn't have to be done at run-time.
If you're interested in using a pointer cast, use the new style pointer casts. The most common example of
these is to change old-style pointer casts such as (X*)p into new-style dynamic casts such as
dynamic_cast<X*>(p), where p is a pointer and X is a type. In addition to dynamic_cast, there
is static_cast and const_cast, but dynamic_cast is the one that simulates most of the
advantages of dynamic typing (the other is the typeid() construct; for example,
typeid(*p).name() will return the name of the type of *p).
[ Top | Bottom | Previous section | Next section ]
[27.4] How do you use inheritance in C++, and is that different from
Smalltalk?
[Recently renamed "subclass" to "derived class" (on 7/00). Click here to go to the next FAQ in the "chain" of recent
changes.]
Some people believe that the purpose of inheritance is code reuse. In C++, this is wrong. Stated plainly,
Smalltalk lets you make a subtype that isn't a derived class, and allows you to make a derived class that
isn't a subtype. This allows Smalltalk programmers to be very carefree in putting data (bits,
representation, data structure) into a class (e.g., you might put a linked list into class Stack). After
all, if someone wants an array-based-Stack, they don't have to inherit from Stack; they could inherit
such a class from Array if desired, even though an ArrayBasedStack is not a kind-of Array!
In C++, you can't be nearly as carefree. Only mechanism (member function code), but not representation
(data bits) can be overridden in derived classes. Therefore you're usually better off not putting the data
structure in a class. This leads to a stronger reliance on abstract base classes.
I like to think of the difference between an ATV and a Maseratti. An ATV (all terrain vehicle) is more
fun, since you can "play around" by driving through fields, streams, sidewalks, and the like. A Maseratti,
on the other hand, gets you there faster, but it forces you to stay on the road. My advice to C++
programmers is simple: stay on the road. Even if you're one of those people who like the "expressive
freedom" to drive through the bushes, don't do it in C++; it's not a good fit.
[ Top | Bottom | Previous section | Next section ]
Yes. It's sometimes (not always!) a great idea. For example, suppose all Shape objects have a common algorithm for
printing, but this algorithm depends on their area and they all have a potentially different way to compute their area.
In this case Shape's area() method would necessarily have to be virtual (probably pure virtual) but
Shape::print() could, if we were guaranteed no derived class wanted a different algorithm for printing, be a
non-virtual defined in the base class Shape.
#include "Shape.hpp"
[23.2] That last FAQ confuses me. Is it a different strategy from the other
ways to use virtual functions? What's going on?
[Recently created (on 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]
Yes, it is a different strategy. Yes, there really are two different basic ways to use virtual functions:
1. Suppose you have the situation described in the previous FAQ: you have a method whose overall structure is
the same for each derived class, but has little pieces that are different in each derived class. So the algorithm is
the same, but the primitives are different. In this case you'd write the overall algorithm in the base class as a
public: method (that's sometimes non-virtual), and you'd write the little pieces in the derived classes.
The little pieces would be declared in the base class (they're often protected:, they're often pure
virtual, and they're certainly virtual), and they'd ultimately be defined in each derived class. The most
critical question in this situation is whether or not the public: method containing the overall algorithm
should be virtual. The answer is to make it virtual if you think that some derived class might need to
override it.
2. Suppose you have the exact opposite situation from the previous FAQ, where you have a method whose overall
structure is different in each derived class, yet it has little pieces that are the same in most (if not all) derived
classes. In this case you'd put the overall algorithm in a public: virtual that's ultimately defined in the
derived classes, and the little pieces of common code can be written once (to avoid code duplication) and
stashed somewhere (anywhere!). A common place to stash the little pieces is in the protected: part of the
base class, but that's not necessary and it might not even be best. Just find a place to stash them and you'll be
fine. Note that if you do stash them in the base class, you should normally make them protected:, since
normally they do things that public: users don't need/want to do. Assuming they're protected:, they
probably shouldn't be virtual: if the derived class doesn't like the behavior in one of them, it doesn't have to
call that method.
For emphasis, the above list is a both/and situation, not an either/or situation. In other words, you don't have to
choose between these two strategies on any given class. It's perfectly normal to have method f() correspond to
strategy #1 while method g() corresponds to strategy #2. In other words, it's perfectly normal to have both strategies
working in the same class.
[ Top | Bottom | Previous section | Next section ]
class implementation can make better use of the derived class's resources) or to get around the hiding rule. However
the client-visible effects must be identical, since non-virtual functions are dispatched based on the static type of
the pointer/reference rather than the dynamic type of the pointed-to/referenced object.
[ Top | Bottom | Previous section | Next section ]
Here's how you get out of the mess: Derived must have a using declaration of the hidden member function. For
example,
class Base {
public:
void f(int);
};
[23.6] What does it mean that the "virtual table" is an unresolved external?
If you get a link error of the form
"Error: Unresolved or undefined symbols detected: virtual table for class Fred,"
you probably have an undefined virtual member function in class Fred.
The compiler typically creates a magical data structure called the "virtual table" for classes that have virtual
functions (this is how it handles dynamic binding). Normally you don't have to know about it at all. But if you forget
to define a virtual function for class Fred, you will sometimes get this linker error.
Here's the nitty gritty: Many compilers put this magical "virtual table" in the compilation unit that defines the first
non-inline virtual function in the class. Thus if the first non-inline virtual function in Fred is
wilma(), the compiler will put Fred's virtual table in the same compilation unit where it sees Fred::wilma().
Unfortunately if you accidentally forget to define Fred::wilma(), rather than getting a Fred::wilma() is
undefined, you may get a "Fred's virtual table is undefined". Sad but true.
[ Top | Bottom | Previous section | Next section ]
Subject Index
(Part of C++ FAQ Lite, Copyright 1991-2001, Marshall Cline,
[email protected])
"A" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
A2PS (see Pretty printing) ... [35.2]
ABC (see also Inheritance) ... [22.2], [22.3]
Access rules
protected: and private: inheritance ... [24.6]
"B" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Backtracking ... [5.3]
bad_alloc (see also std::bad_alloc) ... [16.5], [16.6]
Bag of Apple vs. of Fruit ... [21.3]
Base class ... [19.3]
Beautifier, Code (see Pretty printing) ... [35.2]
Big Picture issues (see Managerial issues) ... [6]
Big Three, Law of ... [16.16], [22.5], [25.9]
Binary compatibility between vendors ... [33.8]
Binding: Static vs. dynamic ... [20.2], [20.3]
Book (see C++ FAQ Book) ... [3]
Books on C++ ... [26]
Books
Design ... [26.8]
Legality issues of C++ ... [26.4], [26.6]
Morality issues of C++ ... [26.4], [26.5]
Programming-by-example in C++ ... [26.4], [26.7]
BTW (Acronym) ... [5.1]
Built-in (intrinsic) types ... [10.6], [10.11], [10.12], [10.13], [13.6], [15.12], [16.12], [16.19], [25.9]
Business criteria dominate technical criteria ... [6.4]
"C" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
C++2LaTeX (see Pretty printing) ... [35.2]
C++ books ... [26]
C++ compiler
"D" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Dangerous programming practices ... [11.5], [11.6], [11.10], [13.6], [16.2], [16.4], [16.11], [16.12],
[16.16], [17.5], [20.4], [21.1], [21.4], [21.5], [23.5], [31.1], [34.5]
Dangling else problems ... [34.1]
Declarations
Declare near first use ... [25.6]
"E" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Ellemtel coding guidelines (see also Coding standards) ... [25.11]
Ellipses vs. Circles ... [21.6], [21.7], [21.8], [21.9], [21.10]
Encapsulation ... [6.7], [7]
Definition ... [7.4]
Hides stuff from code, not from people ... [7.6]
Not necessarily violated by friends ... [14.2]
Security vs. Encapsulation ... [7.7]
End-of-file (see Input/output) ... [15.2], [15.4]
Equation parsing in C++ ... [5.3]
Error codes (AKA "Return codes") ... [17.1], [17.2]
Etiquette (see also Netiquette) ... [5]
Evil things
Macros ... [9.3], [27.3], [34.1], [34.2], [34.3]
"F" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Features of C++ from a business perspective ... [6.7]
Filenames
Extensions for header files ... [25.8]
"G" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Garbage collector ... [16.25]
Conservative ... [16.26]
Hybrid ... [16.26]
Web sites ... [16.27]
Generalization (see also Inheritance) ... [19.3]
Generalized pointers: Handles ... [8.7]
Genericity (see also Templates) ... [31.10]
Global variables: Just Say No! ... [34.5]
GNU
emacs ... [35.3]
"H" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Handles as generalized pointers ... [8.7]
Has-a (see also Composition) ... [19.2], [24.2]
Header files
Filename extensions ... [25.8]
"I" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Idioms
Construct On First Use Idiom ... [10.12], [10.13]
"J" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Java vs. C++ ... [6.4]
"K" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Kind-of (see also Inheritance) ... [19.2]
Kruskal ... [5.3]
KUTGW (Acronym) ... [5.1]
"L" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Language wars ... [6.4]
Large executables ... [32.8], [33.9]
Last rites (see also Destructors) ... [11.1]
LaTeX
C++2LaTeX pretty printer ... [35.2]
"M" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Macros (see also #define macros) ... [9.3]
malloc()
(See also Freestore) ... [16.2]
Multiple inheritance ... [6.7], [11.12], [24.2], [29.8], [29.9], [33.8], [33.11]
mutable ... [18.10]
Mutator methods ... [18.9]
MYOB (Acronym) ... [5.1]
"N" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
"name2()" macro for token pasting ... [34.3]
Named Constructor Idiom ... [10.8], [16.20], [16.23]
Named Parameter Idiom ... [10.15]
NCITS ... [6.12]
Netiquette ... [5]
From: line of a posting ... [5.4]
General netiquette ... [5.4]
Getting and reading other FAQs ... [5.9]
Posting code ... [5.7]
Reply-to: line of a posting ... [5.4]
Selecting an appropriate newsgroup ... [5.8]
Subject: line of a posting ... [5.6]
new
Advantages over malloc() ... [16.3]
Allocating an array with new T[n] ... [16.10]
Mixing with free() ... [16.2]
(See also Freestore) ... [16.1]
New handler (see also Freestore) ... [16.6]
Newsgroups
comp.graphics ... [5.8]
"O" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Object ... [7.2]
Object-oriented: So what? ... [6.3]
Old code calls new code ... [6.9]
OO design books ... [26.8]
?: operator ... [25.5]
operator<< ... [8.4], [15.12]
operator>> ... [15.3], [15.13]
Operator ?: ... [25.5]
Operator overloading ... [6.7], [13]
Assignment operator ... [12], [22.5]
Can't invent new operators ... [13.7]
Can't replace behavior on built-ins ... [13.6]
Coding standards ... [25.9]
Does help the users of a class ... [13.2]
Does not help the developer of a class ... [13.4]
Examples ... [13.3]
operator!= ... [13.10]
"P" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Paradigm shifts ... [6.6], [29.10]
Parameterized types (see also Templates) ... [31.9]
Parameters, named vs. positional ... [10.15]
Parking lots ... [21.3]
Parser for C++ ... [33.10]
Part-of (see also Composition) ... [19.2], [24.2]
"Q" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Quick-sort ... [5.3]
"R" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
realloc() (see also Freestore) ... [16.4]
Recent changes to this document (see also C++ FAQ Lite) ... [4]
Reciprocal: Friendship privileges are not ... [14.4]
Redefining non-virtuals ... [23.4]
Reference counting
Can it be suverted? ... [16.24]
"S" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Security vs. Encapsulation (see also Encapsulation) ... [7.7]
Self-assignment ... [12.1], [12.2], [12.3], [25.9]
Self-cleaning member objects ... [17.4]
set_new_handler (see also Freestore) ... [16.6]
Short-courses (one 40 hour workweek) ... [6.6]
Shortest path in C++ ... [5.3]
Size of the C++ installed base ... [6.5], [6.7]
Smalltalk ... [27]
Differences with C++ ... [27.1]
Dynamic type checking ... [27.2]
Inheritance differences ... [27.4], [27.5]
Language wars vs. C++ ... [6.4]
Not an efficient way to learn OO/C++ ... [26.3]
Smart pointers ... [13.3], [16.21], [17.4]
SO (Acronym) ... [5.1]
Solaris ... [5.8]
Sorting in C++ ... [5.3]
Source filename extensions ... [25.7]
Spanning Trees in C++ ... [5.3]
Specialization (see also Inheritance) ... [19.3]
Stack unwinding during exception handling ... [11.13], [17.3]
Standard headers ... [25.4]
Standardization issues ... [5.8], [6.11], [6.12], [27.1]
Static
Common linker errors due to static data members ... [10.10]
Define static data members explicitly ... [10.9], [10.10]
Initialization order fiasco ... [10.11], [10.12], [10.13]
Named Constructor Idiom using static ... [10.8], [16.20], [16.23]
static at file-scope (Don't!) ... [7.5]
Static binding ... [20.2], [20.3]
static create() methods ... [10.8], [16.20], [16.23]
"T" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
.tar.gz (see Downloading) ... [2.2], [2.3], [2.4]
.tar.Z (see Downloading) ... [2.2], [2.3], [2.4]
"U" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Uncompiling executables back into C++ source code ... [33.4]
Unix ... [5.8], [35.4]
Unresolved external (see also Linker errors) ... [23.6]
"V" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
v-pointer (see also virtual) ... [20.3], [33.8]
v-table (see also virtual) ... [20.3], [21.4], [23.6], [33.8]
Value semantics ... [28], [28.7], [28.8]
vector<T> (see also std::vector<T>) ... [10.5], [16.18], [16.19], [21.4], [21.5], [31.1],
[32.3]
Version numbers to the "language" ... [33.11]
virtual
Binary compatibility of virtual functions ... [33.8]
"W" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Wars ... [25.1]
WWW sites of this document ... [2.1]
"X" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
X3 Secretariat ... [6.12]
"Y" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
Yaccable grammar ... [33.10]
"Z" [ Top | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Bottom]
.zip (see Downloading) ... [2.2], [2.3], [2.4]
Zombie objects ... [17.2]
balanced perspective. The first few have intentionally been slanted toward value semantics, so if you
only read the first few of the following FAQs, you'll get a warped perspective.
Assignment has other issues (e.g., shallow vs. deep copy) which are not covered here.
[ Top | Bottom | Previous section | Next section ]
virtual data allows a derived class to change the exact class of a base class's member object.
virtual data isn't strictly "supported" by C++, however it can be simulated in C++. It ain't pretty, but
it works.
To simulate virtual data in C++, the base class must have a pointer to the member object, and the
derived class must provide a new object to be pointed to by the base class's pointer. The base class would
also have one or more normal constructors that provide their own referent (again via new), and the base
class's destructor would delete the referent.
For example, class Stack might have an Array member object (using a pointer), and derived class
StretchableStack might override the base class member data from Array to
StretchableArray. For this to work, StretchableArray would have to inherit from Array, so
Stack would have an Array*. Stack's normal constructors would initialize this Array* with a
new Array, but Stack would also have a (possibly protected:) constructor that would accept an
Array* from a derived class. StretchableStack's constructor would provide a
new StretchableArray to this special constructor.
Pros:
Easier implementation of StretchableStack (most of the code is inherited)
Users can pass a StretchableStack as a kind-of Stack
Cons:
Adds an extra layer of indirection to access the Array
Adds some extra freestore allocation overhead (both new and delete)
Adds some extra dynamic binding overhead (reason given in next FAQ)
In other words, we succeeded at making our job easier as the implementer of StretchableStack,
but all our users pay for it. Unfortunately the extra overhead was imposed on both users of
StretchableStack and on users of Stack.
Please read the rest of this section. (You will not get a balanced perspective without the others.)
[ Top | Bottom | Previous section | Next section ]
The easiest way to see the distinction is by an analogy with virtual functions: A virtual member
function means the declaration (signature) must stay the same in derived classes, but the definition
(body) can be overridden. The overriddenness of an inherited member function is a static property of the
derived class; it doesn't change dynamically throughout the life of any particular object, nor is it possible
for distinct objects of the derived class to have distinct definitions of the member function.
Now go back and re-read the previous paragraph, but make these substitutions:
"member function" > "member object"
The reason they all look so much the same is that none of this is "supported" in C++. It's all merely
"allowed," and in this case, the mechanism for faking each of these is the same: a pointer to a (probably
abstract) base class. In a language that made these "first class" abstraction mechanisms, the difference
would be more striking, since they'd each have a different syntactic variant.
[ Top | Bottom | Previous section | Next section ]
Freestore allocations can be a performance issue (the performance of the typical implementation of
malloc() degrades when there are many allocations; OO software can easily become "freestore
bound" unless you're careful)
The extra dynamic binding comes from having a pointer rather than an object. Whenever the C++
compiler can know an object's exact class, virtual function calls can be statically bound, which
allows inlining. Inlining allows zillions (would you believe half a dozen :-) optimization
opportunities such as procedural integration, register lifetime issues, etc. The C++ compiler can
know an object's exact class in three circumstances: local variables, global/static variables, and
fully-contained member objects
Thus fully-contained member objects allow significant optimizations that wouldn't be possible under the
"member objects-by-pointer" approach. This is the main reason that languages which enforce
reference-semantics have "inherent" performance challenges.
Note: Please read the next three FAQs to get a balanced perspective!
[ Top | Bottom | Previous section | Next section ]
problem-space objects.
Note that these problem space objects are normally at a higher level of abstraction than the solution space
objects, so the problem space objects normally have a relatively lower frequency of interaction.
Therefore C++ gives us an ideal situation: we choose reference semantics for objects that need unique
identity or that are too large to copy, and we can choose value semantics for the others. Thus the highest
frequency objects will end up with value semantics, since we install flexibility where it doesn't hurt us
(only), and we install performance where we need it most!
These are some of the many issues the come into play with real OO design. OO/C++ mastery takes time
and high quality training. If you want a powerful tool, you've got to invest.
Don't stop now! Read the next FAQ too!!
[ Top | Bottom | Previous section | Next section ]
Nope.
The previous FAQ were talking about member objects, not parameters. Generally, objects that are part of
an inheritance hierarchy should be passed by reference or by pointer, not by value, since only then do
you get the (desired) dynamic binding (pass-by-value doesn't mix with inheritance, since larger derived
class objects get "sliced" when passed by value as a base class object).
Unless compelling reasons are given to the contrary, member objects should be by value and parameters
should be by reference. The discussion in the previous few FAQs indicates some of the "compelling
reasons" for when member objects should be by reference.
[ Top | Bottom | Previous section | Next section ]
A virtual function allows derived classes to replace the implementation provided by the base class.
The compiler makes sure the replacement is always called whenever the object in question is actually of
the derived class, even if the object is accessed by a base pointer rather than a derived pointer. This
allows algorithms in the base class to be replaced in the derived class, even if users don't know about the
derived class.
The derived class can either fully replace ("override") the base class member function, or the derived
class can partially replace ("augment") the base class member function. The latter is accomplished by
having the derived class member function call the base class member function, if desired.
[ Top | Bottom | Previous section | Next section ]
[20.2] How can C++ achieve dynamic binding yet also static typing?
When you have a pointer to an object, the object may actually be of a class that is derived from the class
of the pointer (e.g., a Vehicle* that is actually pointing to a Car object; this is called
"polymorphism"). Thus there are two types: the (static) type of the pointer (Vehicle, in this case), and
the (dynamic) type of the pointed-to object (Car, in this case).
Static typing means that the legality of a member function invocation is checked at the earliest possible
moment: by the compiler at compile time. The compiler uses the static type of the pointer to determine
whether the member function invocation is legal. If the type of the pointer can handle the member
function, certainly the pointed-to object can handle it as well. E.g., if Vehicle has a certain member
function, certainly Car also has that member function since Car is a kind-of Vehicle.
Dynamic binding means that the address of the code in a member function invocation is determined at
the last possible moment: based on the dynamic type of the object at run time. It is called "dynamic
binding" because the binding to the code that actually gets called is accomplished dynamically (at run
time). Dynamic binding is a result of virtual functions.
[ Top | Bottom | Previous section | Next section ]
class Shape {
public:
virtual ~Shape() { } // A virtual destructor
virtual void draw() = 0; // A pure virtual function
virtual void move() = 0;
// ...
virtual Shape* clone() const = 0; // Uses the copy constructor