Appendix F.  Errata

[ fromfile: errata.xml id: errata ]

Errata in the first printing.

This document was last updated on $Date: 2009-06-08 16:01:21 -0400 (Mon, 08 Jun 2009) $.

p.6. “C with Objects”: s/Objects/Classes

p.8, add an item to the numbered list:

  3. It is installed by your package manager as qmake-qt4,
     to avoid conflict with Qt3 packages.

p.22 Table 1.2 should be replaced with:

Table F.1. Simple Types Hierarchy

byte/char typesintegral types floating point types
bool short int float
char unsigned short double
signed char intlong double
unsigned char unsigned int
wchar_t anyType*
long int
unsigned long


p.29 exercise #2: For windows portability, s/random()/rand()/. random() is only POSIX compliant, while rand() is from C standard library.

p.33, Example 1.16, some #include directives should have been included at the top of the listing:

#include <iostream>
#include <sstream>
#include <fstream>

P.58, The constructor at the top of the page should be:


Complex::Complex(double realPart) :
    m_R(realPart), m_I(0) {
}

P.58, Section 2.8 Subobjects should be the last section of Chapter 2 (i.e., after the section, const Member Functions.

P.72, diagram for Problem 3 should be this:

p.83, There should be no semicolon at the end of the code example, main.cpp.

p.83, the qapp.pro is missing a line:

CONFIG += console

P.83, just before the start of section 3.2:

The last line, CONFIG += console, only necessary on Windows platforms, tells the compiler to build a “console” application, which can interact with the user via standard input/output streams.

Page 101, first para: s/Employers many hire many/Employers may hire many/

Page 101, Relationships exercises, some clarification of wording:

P.121, Example 5.14 needs one member function to be corrected so that it reads:

    void setNameR( QString& newName) {
        newName += " Dobbs";  /* changes the original QString */
        m_Name = newName;
    }

Page 137, UML diagram should be this:

Figure F.1.  UML diagram of inheritance

UML diagram of inheritance

Page 138 and 143, In the Student class definition:

Page 157, Example 6.22: use member init lists in constructors:


Account::Account(unsigned acctNum, double balance, string owner) :
     m_AcctNum(acctNum), m_Balance(balance), m_Owner(owner)
    { }

JointAccount::JointAccount (unsigned acctNum, double balance,
                            string owner, string jowner)
    :Account(acctNum, balance, owner),
     m_JointOwner(jowner)  /* base class initialization required */
     { }

JointAccount::JointAccount (const Account& acc, string jowner)
    :Account(acc), /* compiler-generated copy constructor call */
     m_JointOwner(jowner)
    { }

Page 172, section on Installing Libraries, add a note:

[Tip] Building DLLs

There is a thread on the subject at qtcentre.org, which should save you a lot of time when you build your first DLL.

Page 183, example 18.1 - some changes to the code:

QString dirname = finfo.fileName();
if ((dirname==".") || (dirname == ".."))
    return;
QDir sd(finfo.filePath());
if (skipDir(sd))
    continue;
    recurseAddDir(sd);
} else {
    if (finfo.extension(false)=="mp3") {
        addMp3File(finfo.absFilePath()); /* non-reusable part */
    }
}

Some changes to FileVisitor class definition:

Example F.1. src/libs/utils/filevisitor.h

[ . . . . ]
#include <QDir>
#include <QObject>
#include <QStringList>
#include "utils_export.h"
class UTILS_EXPORT FileVisitor : public QObject {
    Q_OBJECT
 public:
    FileVisitor(QString nameFilter="*",
                bool recursive=true, bool symlinks=false);
    FileVisitor(QStringList nameFilterList,
            bool recursive=true, bool symlinks = false);
    
 public slots:
    void processFileList(QStringList sl);
    void processEntry(QString pathname);

    
 signals:
    void foundFile(QString filename);
 protected:
    virtual void processFile(QString filename); 1

    [ . . . . ]
protected:
    QStringList m_filterList;
    bool m_Recursive;
    QDir::Filters m_DirFilter;
};
[ . . . . ]

1

override this

FileVisitor::processDir() has been updated:


Page 187 CodeVisitor class definition has been improved:

Example F.3. src/visitor/codevisitor/codevisitor.h

[ . . . . ]
class CodeVisitor : public FileVisitor {
  public:
    CodeVisitor(QString filter = "*.h,*.cpp", bool recursive = true);
    CodeVisitor(QStringList filterList, bool recursive = true);
    void processFile(QString filename);
    int getNumFiles() const;
    QString getResultString() const;
 private:
    int m_NumFiles;
    QStringList m_Result;
};
[ . . . . ]

Page 188, Example 8.6, codevisitor-test.cpp has been improved:

Example F.4. src/visitor/codevisitor/codevisitor-test.cpp

#include <argumentlist.h>
#include <codevisitor.h>
#include <QApplication>
#include <QTextStream>
#include <stdlib.h>

static QTextStream cerr(stderr);
void usage(QString appname) {
    
    cerr << appname << " Usage: \n"
         << "codevisitor [?] [-r] [-d startdir] [-f filter] [file-list]\n"
         << "\t-?        \tthis help list\n"
         << "\t-r        \tvisitor will recurse into subdirs\n"
         << "\t-d startdir\tspecifies starting directory\n"
         << "\t-f filter\tfilename filter to restrict visits (i.e. -f \"*.cpp\") \n"
         << "\toptional list of files to be visited\n" 
         << "Use double quotes to delimit all strings in command line."<< endl;
}

int main(int argc, char** argv) {
    ArgumentList al(argc, argv);
    QString appname = al.takeFirst(); 1 
    if (al.getSwitch("?") or al.getSwitch("-?")) {
        usage(appname);
        exit(1);
    }
    bool recursive(al.getSwitch("-r"));
    QString startdir(al.getSwitchArg("-d"));
    QStringList filterList;
    QString filter;
    
    while ((filter = al.getSwitchArg("-f", QString())) != QString()) {
        cerr << "added filter: " << filter << endl;
        filterList << filter;
    }
    CodeVisitor cvis(filterList, recursive);
    if (startdir != QString()) {
		// change directory to startdir
        cvis.processEntry(startdir);
    }
    if (al.size()) {
        cvis.processFileList(al);
    }

    cerr << "Files Processed: " << cvis.getNumFiles() << endl;
    cerr << cvis.getResultString() << endl;
    return 0;
}

1

app name is always first in the list.

Page 190, Question 2, “Why Does the FileVisitor need to be Recursive?“ The answer is: It does not need to be. A better question here would be: “How would you rewrite the FileVisitor to not be recursive?“

Page 204, member variable in Examples 9.7 renamed:

    QErrorMessage* message; 

should be

    QErrorMessage* m_Message; 

This change produces changes in two lines of Example 9.8:

Messager::Messager(QString msg, QWidget* parent)
        : m_Parent(parent) {
    m_Message = new QErrorMessage(parent);
    setObjectName(msg);
}

void Messager::shout() {
    m_Message->showMessage(objectName());
}

Page 205, magic numbers -273 and 360 in Example 9.9 should be const int.

Page 223, the diagram for the cardgame exercise should be replaced with this one:

Page 228, Figure 10.3 - ContactListWriter has a duplicated function declaration.

Page 228, remove the word “insertion” from the partial sentence, “We achieve this by defining the following insertion operators:“

Page 287, Example 12.11 should be this:

Example F.5. src/qonsole/keyevents/qonsole.cpp

[ . . . . ]

void Qonsole::updateCursor() {
    QTextCursor cur = m_Logw->textCursor();
    cur.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
    m_Logw->setTextCursor(cur);
}

void Qonsole::execute() {
    QByteArray bytes = m_UserInput.toUtf8();
    m_Bash->write(bytes);
    m_UserInput = "";    
}

Page 315, Example 13.4, there are mistakes in nlformat and nlformat2 regular expressions.

QRegExp nlformat ("(\\+|00)?[\\s-]?(31)[\\s-]?(\\d\\d)[\\s-]?(.*)$");
QRegExp nlformat2 ("(\\d\\d)(\\d\\d)(\\d{3})");

Page 512, array example should be this:

   int a[] = {10, 11, 12, 13, 14, 15};
   void f(int a[]) {
      [ ... ]
   }
      [ ... ]
   f(a);

Page 596, small typo:

    s/unable/enable

p. 601 [qttestlib]

s/Harris/Hards