C++ for C Programmers, Third Edition

by Ira Pohl

Addison-Wesley isbn 0-201-39519-3

Extensively revised and updated, this proven book by noted C++/C expert Ira Pohl is written specifically for C programmers who are transitioning to C++. C++ For C Programmers, Third Edition takes an evolutionary teaching approach, using C as a starting point and C++ as a destination. This third edition reflects the new ANSI C++ Standard, and covers the latest language features--including detailed discussions of templates, STL, and exception handling. If you already own the second edition, many of the language changes can be also be found in my C++ Distilled Book which is around $20.00 and is meant to be an informal reference - with selected tips and examples to the new ANSI standard.

Each chapter contains a brief examination of Java that compares and contrasts it with C++, providing the C programmer with a more complete understanding of both C and C++ and their relationship to Java.

Features

You can buy this book online through Barnes and Noble. Ira also offers three on-line courses on C++.

If you are not conversant in C, then the book C++ by Dissection is an excellent start for the professional programmer who wants to master C++ for use in an object-oriented environment. No knowledge of C is required. T

The C++ code examples in the book are available in several forms. The code is arranged in directories corresponding to the chapters of the book. To get to the unpacked version for any system, or to get individual program files, you can use the FTP directory (www.cse.ucsc.edu/~pohl/CPP3/). Files are also available in zip form for Windows users and compressed tar form for UNIX users.


Additional C++ Code Examples

Ira has provided additional code to demonstrate dynamic cast, complete clock program, multiple inheritance, mutable members, string constructors, and rvalue vs. lvalue.


Errata

Caveats: Some standard libraries may have been modified since this book was written and the function prototypes may differ from what is available on your compiler. Check your compiler vendor for the correct prototypes.

Notations: p425 means page 425  
                            +8 means 8 lines from top 
                             -7 means 7 lines from bottom

If you encounter errata in this book not listed here, please contact Ira Pohl via email at pohl@cse.ucsc.edu with your errata. You will be cited in the correction if you are the first to report it.

Acknowledgements: Special thanks to Sharon Harvey of Normandale Community College and David Hiebeler of Cornell University.


p21 (Ming Lai) line 6 The colon after int f(int) should be a semi-colon. There should not be a semi-colon after double f(double).

p30 (Ming Lai) top comment on program. devisor should be divisor


p31 (Sharon Harvey) This is just a question. I was wondering if you could tell me what the "throw new exception();" does in the sample program on page 31.

new exception() allocates an object of type exception which is thrown. This is a simple way to throw a generic exception which will in this case terminate the program. See section9.9 "Standard Exceptions and Their Uses".

The program was writtenly differently from the second edition so as to illustrate some new features. However it is not best practice in my opinion to terminate the program using a throw. Instead I would prefer a prompt that included " a value of 0 terminates this program" and then test for this value with a normal return from main().


p37 (Uwe F. Mayer) line -10 The following wording is awkward:

Where the inline keyword modifies a function definition, it suggest to the compiler that when invoked, the code defining it avoid function call by being compiled inline.

Need to be

Where the inline keyword modifies a function definition, it suggest to the compiler that the function should be compiled inline, thus avoiding the function call logic when it is invoked.


p77 (Ming Lai) line -4 main.c should be cir_main.c


p80 (Ming Lai) 2nd bullet entry # ifdef should not have a space; it should be #ifdef


p89 (Uwe F. Mayer) line 1 "most compilers will issue a warning only if the return value ..."

needs to be

most compilers will issue only a warning if the return value ...


p90 (Ming Lai) line 6 #define should instead be const


p93 (Henry Voss) line -2 s[3] = '0';

needs to be

s[3] = '\0';


p94 (Sharon Harvey) function strcmp, should use && (ands) rather than || (ors) "s1[i] && s2[i] && (s1 ......",

Needs to be:

   int i;
   for(i = 0; s1[i] && s2[i] && (s1[i] == s2[i]); ++i)
Better is :
   for (int i = 0; s1[i] && s2[i] && (s1[i] == s2[i]); ++i)
Simpler is :
   int i; /* need to declare here because of use past the for
	     statement - see discussion on page 47  */
   for(i = 0;  (s1[i] == s2[i]); ++i)
     if (s1[i] == 0)
	return 0;
   return (s1[i] - s2[i]);

p97 (Sharon Harvey) line 5 counts are off by one

   for (i = lb; i < lb + size; ++i)

Needs to be:

   for (i = lb; i < lb + size - 1; ++i)
 

p102 (Ming Lai) line 4 has s1 twice instead of s1 and s2. Change it to cin >> s1 >> s2.


p108 (Sharon Harvey) exercise 5: recursive function call does not need r. Better wording and coding is:

5. We wish to count the number of recursive function call by gcd(). ...

   static int fcn_calls = 1;    //happens once
int r; //remainder

fcn+calls++;

Needs to be:

5. We wish to count the number of function call by gcd() as coded recursively. ...

   static int fcn_calls = 0; //count function calls
   fcn_calls++;              //recrusive computation

p. 115 (Sharon Harvey) Missing semicolon at end of structure

 struct point {
double x, y;
} Needs to be:
struct point {
double x, y;
};

p117 (Uwe F. Mayer) line -2 before the table. The wording "the two accessing modes can..."


needs to be

the two access modes can


p132 (Uwe F. Mayer) line 10 const ch_stack::int max_len = 1000 should not have the int specified.

needs to be

const ch_stack::max_len = 1000

p. 132 (Paul Ezust)

On P.132, in your example mutable.cpp, the function person::bday() must be declared const in order for the compiler to permit it to be called via the const object ira.

With or without mutable, a const object can only invoke const member functions.

If you change it to:

void bday() const { ++age;}
The program compiles and the mutability point is made.

Needs to be:

The indicated change corrects the problem. The following code is a small variation on the book that incorporates the correction.

#include <  iostream  >
#include <  string  >
using  namespace std;

class person {
public:
  person(const string n, int a, const unsigned long ss)
      :name(n), age(a), soc_sec(ss){}
  void bday() const  {++age;}
  void print() const
  { 
     cout << name << " is  " << age 
     << "  years old with SSN  " << soc_sec << endl;
  }
private:
  const string name;
  mutable int age;
  const unsigned long soc_sec;
};

int main()
{
   const person ira("ira pohl", 38, 1110111UL);
   ira.print();
   ira.bday();
   ira.print();

}

page 133 (Sharon Harvey): The print( ) and where_am_i( ) functions in class point should be declared as const functions.

void print () const { ...

point* where_am_I() const { ...


p139 (Ming Lai) line -5. The closing paren and opening brace are missing. The line should be

public String toString() {


p 143(Sharon Harvey) exercise 5 : The function reverse() should be const correct:

Needs to be:

void reverse(const char s1[], char s2[]);
Const correctness while not essential is desirable because it improves program correctness and readability. It clearly identifies s1 as an input variable thatshould not be modified. It also may be useful to the compiler for optimization.


page 153 (Sharon Harvey): line -10

The print( ) function should be declared as a const function.

void print () const { ...


p155 (Uwe F. Mayer) line -16 "In ANSI C++ Compiler"

needs to be

In ANSI C++


p 160 line 21: The function my_string() has a memory leak.

Needs to be:

void my_string::concat(const my_string& a, const my_string& b)
{
   ...
   delete []temp;
}


p173, 174 (Sharon Harvey) function element() is no longer declared a const function, as it was in the 2nd edition, even though none of the data members,p, s1, and s2, are modified in the function.

Should be written for const checking as:

double& element(int i, int j) const;
{
   ...
   return p[i][j];
}


p199 (Sharon Harvey)

Is the output correct for rational.cpp? For the third line of output, I was wondering how cout would be able to print a rational object. I was wondering if the print() function was needed for this. And for the fourth line of output, I was wondering if the result would print as "greater(1000 / 100, 350 / 100) = 1000 / 100" rather that "greater(10 / 1, 350 / 100) = 10 / 1".

I didn't see where the rational number was getting reduced in the program code.

The output is correct

  greater(10, 5) = 10
  greater(7, 14.5) = 14.5
  greater(10, 350 / 100) = 10
  greater(10 / 1, 350 / 100) = 10 / 1
The third output is triggered by a call to the function greater() which results in printing 10. The cout << does not know how to print a rational but operator double() performs a conversion of the rational to the double 10. This cout knows how to print.

The fourth results is based on comparing two rationals. The winner is 10 / 1. This therefore is what gets printed. There was no internal change to its representation.


p200, 2nd point in dissection (Sharon Harvey) "second" should be "third" in the following: greater(static_cast(i), z); The second definition of greater() is selected because of the exact-match rule."

Should be:

The third definition of greater() is selected ...


p207 (Sharon Harvey)

I noticed the following typo on page 207 in the second to the last sentence in Section 6.5.

"+c is equivalent to c.operator++( )."

+c should be ++c in the line

Should be:

++c is equivalent to c.operator++().


p221 (Uwe F. Mayer) line 12 x(unsigned size)

needs to be

x(size_t size)


p233, exercise 15 questions (Sharon Harvey)

I have a question on Exercise 15, page 233. If operator[] returns -1 to indicate an invalid string index, the return type will need to be int, rather that char. But the user will be expecting a char. What's a good way to handle this? Thanks so much! - Sharon

Discussion:

Here we have a question of how to treat an error condition. The value -1 is a legal signed char value, so it can be used to return an error condition. So it is unnecessary to make this type int. Possibly a better solution is to throw an exception or abort using an assert if the index is out-of-range.


p236, exercise 24 questions (Sharon Harvey)

1. Concerning the line "c++; // adds a second". How does the program know which function to invoke for the call c++;, the prefix operator defined on page 205, or the postfix operator from Exercise #24, on page 236?

2. Concerning the code "Class T....void operator++(int);", should the return type be clock, rather than void, to remain consistent with the previously defined prefix operator on page 205 and with the predefined ++ operator and its use with the built-in types?

Thanks. - Sharon Harvey

Explanations:

1. c++ is postfix so operator++(int) definition is invoked

++c is prefix and would invoke operator++()

2. Yes for consistency the return type should have been clock.

This is a better design though the language rules do not require this consistency. Also for conceptual consistency postfix should return the existing value of clock upon invocation. The semantics should parallel ++i versus i++ where i is an int.


p240, line 1 and 2 have wrong page and section references (Sharon Harvey)

Should be:

"We shall modify the ch_stack from Section 5.2.1, "The Copy Constructor", on page 157..." should read "We shall modify the ch_stack from Section 5.2, "Constructing a Dynamically Sized Stack", on page 155..."


p263 (Uwe F. Mayer) line 2 Some mutating function ...

needs to be

Some nonmutating function ...


p303 (Uwe F. Mayer) exericse 3 doesn't compile. The rules on access have changed since first developed. Ignore this exercise. It will not compile.


p309 (Uwe F. Mayer) line 4 extra //1) the line if (n < 1) //1)

needs to be

if (n < 1)


p317 (Ming Lai) first program section uses illegal in regular code font when it should be in italics, indicating that it is replaced by something else. It should read

   if (illegal_argument1)
     throw expression1;
   if (illegal_argument2)
      throw expression2;

p318 (Ming Lai) line -4 should replace ANSII with ANSI.


p333 (Ming Lai) line 6 would be better if the word "by" at the end were deleted. It should read as follows: "... enough to judge a design."


p361 (Uwe F. Mayer) line 3 Inside a block, extern indicates ... is incorrect.

needs to be

Inside a block, static indicates ...


p372 (Uwe F. Mayer) line -8 THe

needs to be

The


p388 (Uwe F. Mayer) line -10 "in the next section"

needs to be

in Section 5.5, "The Class dbl_vect" on page 164.


p394 (Uwe F. Mayer) line 5 the comment // conversion constructor should be on one line. Move it left so that it fits.


p416 (Uwe F. Mayer) line table entries

skips white space has an extra space in front - move it left one space

fill characters.. needs to be fills characters (3x)


p417 (Uwe F. Mayer) line -4 "last line of output, lit ..." has lit in code font.

needs to be

last line of output, it ...

 


p 463, 473, and 475 (Uwe F. Mayer) line -8 add page 81 to the :: scope resolution operator entries.