It is also a pain to set up for a small project.
And it takes a makefile on UNIX to work simply..... more later.
I have stored a set of files on the WWW which are ready to be used whenever you need a main program use [ main.cc ] For a a class definition use [ class.h ] To define the implementation of a class use [ class.cc ] For a declaring a single function use [ function.cc ]
Please use them!
Notice keywords: class, public, private.
Notice the #ifndef & #define - and why its needed!
Notice the semicolon at the end of the class definition and the function prototypes.
private:
. . . . . . . . . ( end of section Defining a Class) <<Contents | End>>
Implementing a Class
Notice that implementation #include the header.
Notice the double_colon in the function implementations.
Notice the absent semicolon at the end of the function implementations.
Notice: lots of small functions. Highly modular.
Constructors
Describe how to create a new object - initial values and
things like that. Use them!
Syntax and Semantics -- VITAL
Read, use, practice, remember those in the book! Here are
my personal notes on the syntax and semantics of classes.
For more: [ Object in objects.glossary ]
Struct vs class
A struct assumes things will be public but a class
assumes that things will be private.
Example: Suppose a program declares:
struct S { int i; };
S s;
class C { int i; };
C c;Then s.i will compile but c.i will not.
(struct_style): Use struct for objects that have a structure but
no defined operations/functions.
How to use Objects
You can't use a class as an operand! You can use
objects (in a class) as operands. There are three simple ways
to do this:
. . . . . . . . . ( end of section C++ Classes) <<Contents | End>>
Organizing and compiling your code
Key point: A reusable piece of code has two parts: a
definition and an implementation. The definition tells
the compiler what a client is permitted to do with
the reused code. The implementation tells the computer
how to meet the permitted requests. Notice that it
is not necessary for the compiler to use the implementation information
to figure out how to to compile client code.
Simple but Slow
Put the definition and the implementation on the
same file: foo.cpp say. Tell the compiler to
read(include) foo.cpp as it reads and compiles
the client program:
foo.cpp
client.cpp
Q client.cpp
Note. You can set up 'vi' to do this when you are in command mode and tap 'q'. Simple....
This is what the compiler actually compiles:
Problems: must recompile the whole of foo.cpp every time you compile the client. If you share foo.cpp with other people they must be able to read the whole of it and may rely on you never changing the implementation. Finally you work with a large foo.cpp file.
Separate Definition from Implementation
Place the definitions in a file called foo.h
and the implementation in foo.cpp. Note, that the
implementation must know what the definitions
are and so it must include foo.h. The client tells
the compiler to include foo.cpp and foo.cpp includes foo.h:
foo.h
foo.cpp
client.cpp
Q client.cpp
You can now work on the implementation file without touching the definition file. This may save time editing. It also encourages you to freeze the definition. The programmers who write client code will be thankful!
Problem... we still compile the whole of the implementation every time we compile the the client.
Precompile the details
foo.h
foo.cpp
g++ -c foo.cppThis generates an "objectcode file": foo.o That can be reused without being recompiled. You can give people copies of foo.h and foo.o and they will not be able to read (and steal?) your foo.cpp code.
client.cpp
Compile the program in two stages. Only if you change foo.cpp or if foo.cpp has never been compiled.
Compile client.cpp and link in foo.o by this command:
g++ -o client client.cpp foo.o -lm ...
This works because compiling the parts of the solution is a separate task to linking them together.
Complex projects
When you have many pieces of code and many clients it
helps to spend time documenting the rules and letting
your systems "make" program decide the optimum set of
steps to recreate an uptodate program. On UNIX you
create a "makefile".
For example I have a complex program abc.cpp that uses three pieces of code a,b and c. Another program in the same project is called ab.cpp and only uses a and b. Each reused piece of code is split into a header defining the code and an implementation file:
a.h
abc.cpp
Thus we want to precompile a,b, and c giving a.o, b.o, and c.o precisely when the relevant files are changed. We don't need to recompile b or c if only a has changed. We do not need to compile abc, a,b, or c when ab changes. and so on.
These facts can be recorded in a special file for the project called `makefile'. This lists each thing plus a list of the things it depends on. Then it gives a set of instructions for making the target file out of its dependents. The commands must by preceded by a TAB character, or the 'make' program will not work.
(makefile):
abc: abc.cpp a.o b.o c.o a.h b.h c.h
g++ -o abc abc.cpp a.o b.o c.o -lm
ab: ab.cpp a.o b.o a.h b.h
g++ -o ab ab.cpp a.o b.o c.o -lm
a.o: a.cpp a.h
g++ -c a.cpp
b.o: b.cpp b.b
g++ -c b.cpp
c.o: c.cpp c.h
g++ -c c.cpp
make abcOr since 'abc' is the first thing in the makefile we can just type:
makeTo compile ab.cpp do this:
make abetc. Similarly whenever you change any file, you just input a make command and the make program will do the minimum work needed to reconstruct the new programs.
Q also understands Makefiles and make and will use them if you have them:
Q abc.cppwill call make abc for you.
For more information on make, look in the UNIX manuals:
man makeor look at [ make.html ] and [ makefile.FAQ ]
. . . . . . . . . ( end of section Rough Notes on Objects and Clases) <<Contents | End>>
Abbreviations