Use for when counting or taking each item in a vector, array, string, etc. in turn.
Notice that
for(A; B; C;) Sdoes the same thing as
{ A;
while(B)
{
S;
C;
}
}
As a rule --
(KISS): Keep It Simple ...
Use an array only when you know, for an absolute fact, how many items you will need or (for experts) when you can calculate the absolute maximum number of items. Otherwise use vectors or dequeues.
They will be in the labs. I'll try to keep them out of the quizzes and final. They may be part of some projects. They have to turn up in several lectures/discussions.
In lab02 I will try to convince you that arrays can be dangerous. We will do more with arrays in class as well.... in particular we will wrap one up in a class so it can be used safely.
A vector is like an array but it's size can change. It lets you push new items on to it at one end, and also remove (pop) them from the same end.
A deque Is like a vector except you can push and pop at both ends.
Here is an application of a deque -- simulating the line in the Arrowhead Post Office in North San Bernardino. People come in and join the line at one end and leave it at the other... but sometime somebody comes in joins the end (push_back) and, before any one else comes in, they give up and leave (pop_back).
Note: There are also stacks and queues. A queue you 'push' at one end and 'pop' at the other. A stack you 'push' and 'pop' at the same end. More later on [ stl.html ] when we cover the Standard Template Library.
v=e //v is a variable, and e an expressionEvaluates e, and takes the value and stuffs it into v.
e1==e1 //e1 and e2 expressionsEvaluates BOTH e1 and e2, and compares them. If they are equal it return true otherwise false.
int twice(int i) { return i+i;}
double twice(double i) { return 2.0*i;}
string twice(string i) { return i+i;}But they all do similar things.
The compiler picks the right one, so it is a waste of time giving them different names.
double s=0.0;
for(int i=1; i<5; i++)
s=s+i;
Variables | s | i |
---|---|---|
Command | double | int |
double s=0.0; | 0 | |
i=1 | 0 | 1 |
i<5? | ||
s=s+i; | 1 | 1 |
i++ | 0 | 2 |
i<5? | ||
s=s+i; | 3 | 2 |
i++ | 3 | 3 |
I<5? | ||
s=s+i; | 6 | 3 |
i++ | 6 | 4 |
i<5? | ||
s=s+i; | 10 | 4 |
i++ | 10 | 5 |
i<5? FALSE |
Avoiding guessing until you've traced it, step by step,...
You can learn a lot about it from working out what a simple (useless) program does: [ 02rec.cpp ] , for example.
If you haven't figured it out yet, try this link [ lookup.php?search=recursive ]
Use a sentinel when normal humans provide the input.
Use CTRL/D or CTRL/Z when the data comes from a file, another program, or a three star computer geek.
Is the data a measurement? Is it approximate? Can it have fractions? Then use double.
while(C){B}does this
C; B; C; B; ...; B; !C
The do-while loop
do{B}while(C)does this
B; C; B; ...; B; !C
Array | Class |
---|---|
is an object | is a data type |
has numbered items | has objects with named members |
is old fashioned | is object oriented |
(exception -- there may be an problem in the book that needs binary input/output).
Waring: lots of binary conversions needed in hardware classes.
They are used to communicated addresses to functions in parameters so that the function's code can aces and change the outside data.
They are used simply because a pointer takes up 4 bytes and can refer to an array or object with 10,000 bytes of data. It is much quicker to pass the 4 bytes than copy the 10Kb!
Pointers to char are used to implement <string>.
The address of an array is a pointer and so pointers are used to share arrays of data with functions.
Pointers are used to remember where data is, when we create data on the heap -- because we didn't know until the program ran how much data to store.
Pointers are used to link objects together -- one object knows where to find another object because it stores the address of the other object.
C and C++ solve lots of technical problems by using pointers.
The asterisk is used in declaring pointers.
First all pointers are declared like this:
T * v ....;where v is a variable and T a type (or class name).
An int is stored in a location and has an address. It has a value that is an int. A pointer to an int (int*) is stored in a location, and has an address. However, the address contains another address. This address contains an int.:
int i = 5;
int* cp = &i;//the address of i
//Now *cp is 5.
T *p...but a reference like this
T&r...Both name addresses but
Property | Pointer | Reference |
---|---|---|
declared by | T*p... | T&v... |
address is | p | - |
value is | *p | r |
points at | changes | fixed |
age | old | new .Raw safe? NO YES |
sizeof(a)/sizeof(a[0])
void name(...)...or to state that it must not have arguments/parameters:
....name(void)...
Then people used void* to mean: a pointer at an object of unknown type.
while( *(p++) = *(q++) );You might guess that this is a test for equality. But beware such naive mistakes. The equals sign in C/C++/Java is a command to copy the data even inside a condition like
while( .... )The
*(p1) = *(q1)copies an item from one place to another.
Next trick the pointers are move on to the next place (p++) and (q++) after the assignment.
So what is tested? When an assignment finishes it leaves a copy of the value behind that can be tested! In this case the character moved. When a null character ('\0') is moved the loops stops.
Next trick the pointers are move on to the next place (p++) and (q++) after the assignment.
So what is tested? When an assignment finishes it leaves a copy of the value behind that can be tested! In this case the character moved. When a null character ('\0') is moved the loops stops.
They are used in special containers to connect a key (a name say) with some data (the person's phone number).
Example: my watch.
In C++ the operations that an object can do come from it's class.
Example: My watch is a Digital Watch. A Digital Watch is a special kind of Watch.
In the real world there are three relationships:
Table
Relation | Means | Example | UML | |
---|---|---|---|---|
ISA | is a special kind of | Male is a Person | Male---|>Person | |
HAS A | has a | A Person has two Legs | Person <>-->Legs | |
KNOWS | can access | A Bank knows its Customers | Bank--->Customer |
It also impresses people in job interviews.
Learn to start solving a problem by listing the classes of object and how they are related -- in the real world.
Allocate operations to the classes in the problem so that they do useful work.
Cat stranger;
...
cout << stranger.stroke();Answer: output "purr".
The compiler looks at the type of object stranger is and finds out that stranger is a Cat. It, therefore replaces stranger.stroke(); by a call to a function stroke in class Cat -- with the variable this pointing at stranger. The operations inside this function stroke all refer to the data in the object stranger. As a rule you find the data in the object and the function in the class. So all objects share the "member" functions.
int read_min() { return m; }could be rewritten as
int read_min();as long as we later, outside of class Clock wrote
inline int Clock::read_min() { return m; }
Inline functions should be small and simple -- one line max. It is normal to define [ Getters and Setters ] (below) as inline functions.
int getM() const { return m; }The const tells the C++ compiler that we won't be changing any variables in the function.
Similarly a Setter is a function that sets the value of a private variable ... use these only when needed and safe. If we needed a clock where the minutes could be set to a value we might write:
void setM(int m0) { assert(0<=m and m<=60); m=m0; }
vector<double> f(data);and its implementation for class C might be like this
vector<double> C::f(data) {vector <double> result; ...... return result; }You could call it like this
myVector= myC.f(myData);
However -- returning large amount of data (a vector can have a million items) slows down programs and should be avoided if possible. This is a classic case for using pass by reference:
void f(data, vector<double> & result);with implementation like this
void C::f(data, vector<double> & result) { ...... return result; }You could call it like this
myC.f(myData, myVector);
It is rather like owning a clockwork watch with no case. It breaks down because of stuff getting into it.
As a rule: data should be private and most functions are public. Make a function private if there is a way for it to be misused.
Class object(data);or get a new object
Class * pointer = new Class(data);
blah example(char * s)....
char a[10] = "hello";
.... example( a)...
A friend function must not have an object when it is called.
The commonest friend functions are those that input and output objects.
More in the next [ 06.html ] class.
Rule: short functions are best inline. Long ones should not be inline.
Unlike many books and some instructors I encourage you to include small function bodies in your "header files" and class declarations. This is more a practitioner's approach than a purist's guide line. A small function/constructor/destructor is no more than one line long:
It get_it() const{return it;}
void set_it(It is) { it=is;}(The above are typical of the many boring short function we write for some classes).
As a rule: use initialization lists whenever the arguments to a constructor provides values for data members/fields/attributes.
class Pair{ public: int first, second;} x,y;
x.first=1; y.first=2; x.second=y.first; y.first=x.first++;
Because all constructors in a class have the same name, the identifier is overloaded. They must have different kinds of argument.
If one actually wants to stop others from constructing new objects, then you merely define constructors as private functions. This is sometimes useful.
The Counter class has a simple example, above. There will be more in other classes.
Classes make programs that are clearer and easier to modify: many small independent pieces.
Call by reference means that the address of the variable in the call is passed to the function and all actions done to the parameter actually are done to the object. This is mainly used to allow data to flow in and out of the function through a parameter.
Notice it is faster to use call be reference (&) with objects -- the object will have more bytes in it than an address. Copying bytes takes time.
Also -- we used to get the same effect by using '*' and '&' but this needs a great deal of knowledge and care to work without bugs.
Use them as little as you can. They expose the object to abuse by the friends.
The input and output functions (operator<< and operator>>) are the main functions that you MUST define as friends in a class in the course.
object.example(data)then, invisibly, the program does this
this = & object;before the function starts to execute. Thus the function knows where the object is.... and can use the information in several ways.
A common way is to tell another object about 'this' object:
user_interface.addButtonListener(this);which means that when the user clicks a button 'this' will be called with a description of the event.
There are other uses for this to be covered later. Most of these use
*thisto refer to the current object -- say to send a message to itself!
Static data belongs to its class, not to the individual objects. It is shared by all the objects. Its value doesn't change when you change objects.
Use it when the data is about the whole class not about one instance/object of the class.
The Wikipedia [ Static_variable#For_class_variables ] has a couple of examples -- one in C# and a simpler one in C++ They define a class of Requests. Each Request is for a particular URL (place on the web), but the class, itself maintains a count of created Requests. This would be used to keep track of how many outstanding requests for web pages have been made, and whether there is a problem or not.
Other examples is a class recording the enrollment in a section of a course. The size of the enrollment is a shard "static" number, each enrollment is for a specific student who is enrolled in a particular section.
In fact, most academic examples of static class members are of counters!
1 + 2
int(rand()*26)+'a'
Seriously: const protects data for abuse -- use it to control bugs.
It effects how this expression or statement is executed
p->f(...)when p is declared
B * p;but p points at an object thta is in derived class clled D (say).
If f is not virtual then the compiler chooses B's version of f. If f is virtual, it delays the decision until the program is running. The program calculates the D version of f.
The classic structure has a class
class Derived : public Base {....};and the program has a pointer to the Base:
Base * pb;which is then attached to a Derived object:
pb = new Derived (....);Now if 'v()' is a virtual function
pb->v();
But if "f()" is not virtual then the command executes "Base::f()".
As a rule we nearly always need pointer to work like the things they point at. (Think demo with magic wand in class). SO virtual gives fewer surprises.
In my opinion you should make all functions virtual (except in toy programs). My evidence -- Java.
Notice the above example of the Aim High pattern of declaring pointers to the most general class.... even if their values are the addresses of low-level special objects.
A dynamic cast makes the program treat a pointer as if it pointed at the lower level objects. Simple example is casting a pointer from Animal to Cat.
It can fail and produce a NULL pointer if this makes no sense -- for example casting a pointer to Animal to being a pointer to Table.
For example the value of a variable has dynamic binding. A constant has a static bound value. The length of an array is statically bound. Data members in a class are statically bound. And the type of a variable is bound by the compiler -- statically.
Virtual functions are bound by the running program.
As a rule dynamic binding is slower, more powerful, and more popular.
class List{
private:
class Node { public: int data; Node * next };
...
};//end ListOutside (if it was public) it would be called "List::Node".
By the way -- Java 5.0 does have nested classes!
By the way -- the word "static" is abused in C++.
A classic example is keeping a count of all the objects that are constructed. The static data member
static int count;is declared and each constructor includes "count++" and each destructor "count --". After the class declare
int Class::count = 0;and the class will know how many instances have been created. Mor -- every object in the class has acess to count and can use it as if it was their own data.
I had another variation when I wanted to be sure that every object had a unique identifier. I used a static int to keep track of the last identifier I had used....
Static functions can be useful when we don't know what object to work with, or when an object has to be constructed. In fact every constructor in a class is static already. But I had a couple an example recently -- what object should handle a Student login? Problem -- I can't give this responsibility to a Student until I find the Student concerned. And I don't want to create a new kind of object solely to find STudents for me -- surely this belongs as part of the Student class! So I decided to make the class as a whole search the students for the correct student Id.:
static Student * find ( string name );So I could have code like this:
string name, passwd;
cout << ....
cin >> name >> passwd;
Student * student = find(name);
if( !student) error("no such student");
else {
.... * student ...
}By the way ... finding the Student with a given name is a classic problem that has several known algorithms and data structures that are part of Computer Science. .What arrows are used in the UML The ones used betweeen classes are here [ links.png ] and there are many other in other kinds of diagrams.
I must prepare a cheatsheet.
Use a diagram when it gets complicated -- 10 or more of them.
Typically an algorithm is used to design the code inside a function.
As an example: the problem is to find the Student that has a given name.
Here is an algorithm called sequential search:
The steps go:
Note --- putting UML diagrams where people can see them in your office or cubicle, is a lot more impressive than a picture of your favorite pop star or film actor.
try {
function();
} catch (...) { cout << "Catch\n"; }
void function()
{
....AS_is throw 42;
...
}
class mine: public standard {
{ public: mine(....) : .... {}
...
};
On a Linux machine -- the code has a bug. Get an update... or join the people who develop open source.
You will see these turn up as things like
ios:app(signals opening a file for appending new data after the existing data).
Formatted input takes in characters and parses them, figures out what data they represent, and puts the result in a variable or object of a particular type. The translation depends on the type of the variable or object. There are predefined input for all predefined data types: ints, floats, etc. Many different codings are allowed as well.
Consequence: formatted input is slower, more powerful, more likely to fail, and most often used.
In the worst case scenario you end up writing a small compiler...
Do you feel like being a magician and experiemnting with iomainpulators? If so see [ Do-it-yourself Manipulators in iomanip ] which shows you how to define some simple ones.
Use this instead:
fabs(x-y) < the_acceptable_error
This is also true of using == and != in an if or a while.
Notice that "i" and "o" are used consistently to indicate "input" and "output".
I've never found a use for it, yet.
Notice: it does not change how values are calculated. Calculations are done in double length in C++. It just controls what the user of the program sees.
But if the file consists of a long series of records that are all the same length, you can use "seekg" to jump to the record to change and read it into primary memory, then edit the data in memory, seekp back to the start of the record and put the updated data back into the record.
If you have a program that needs to both read and write data to a file use an fstream.
11peek name_of_fileand so these programs need to get this information. The operating system puts the arguments into the arguments of main.
Name | Library | Notes |
---|---|---|
vector | <vector> | indexed contiguous sequence |
deque | <deque> | vector grows at both ends |
stack | <stack> | LIFO, push, pop, top, empty, size |
queue | <queue> | FIFO, push, pop, first, last, size, empty |
priority_queue | <queue> | Biggest floats to top, push, pop, first, last, size, empty |
list | <list> | slice, dice, insert, sort, ... |
set | <set> | ordered collection of unique items, intersections, union, etc |
multiset | <set> | ordered collection of items, intersections, union, etc |
map | <map> | ordered set of pairs, first key to unique items,..., general array |
multimap | <map> | ordered set of pairs, first key to items,..., general array |
functions | various | Yes, functions are also objects. There are functions that have functions as data and produce functions! |
streams | <iterator> | Access files, cin, cout using iterators and algorithms |
Inside each application are search engines, data bases, containers, iterators, and algorithms -- and nearly all of them come from computer science.
Example: The set of students on my roster.
pair(x,y)and each x has no more than one y. WHat is cool is that if m is a map associating each X with a Y, then
m [x]is the y. More you can use assignment to add and modify the pairs:
m[x]=y;
function_object(arguments)In other words
T operator () (arguments){....}
Here is a dumb example [ testFillGen.cpp ] of using function objects.
THink of a the pwer adapters you use when you visit a foreign country.
We won't use them any quizzes or the final but I may be forced to use one in a lab. You may find them helpful after you graduate.
Type of Iterator | Operations |
---|---|
Random access | *, =, ==, ++, --, +=, -=, [], ... |
bidirectional | *, =, ==, ++, -- |
Random access | *, =, ==, ++ |
Often, you can find a predefined container/algorithm that does what you want better than you could. It is likely to be faster and cleverer than anything you could do quickly.
You shouldn't need to use them in CSci202, but you may find a use for them in your future career. For example, do rapidly develop a version of the quicksort algorithm I needed to use the partition algorithm and that needed me to define a predicate that was true for all items less than or equal to a particular value. To do that I used a function adapter to convert the predefined less_equal function object into the predicate I wanted:
bind2nd(less_equal<int>(), value)Key point: I didn't expect to ever use this clever feature of C++, but did so this week.
Key points?
map<string, int> directory;
directory["Dick"] = 5327;
Math | C++ example |
---|---|
Subset | includes(A1,A2,B1,B2) |
Union | set_union(A1,A2,B1,B2, C); |
Intersection | set_intersection(A1,A2,B1,B2, C); |
Difference | set_difference(A1,A2,B1,B2, C); |
namespace::namebut this gets old quickly. Instead we can write
using namespace whatever;
Some older compilers let you be lazy and leave out the using namespace.
copy(v.begin(), v.end(), ostream_iterator<int>(cout, "\t"));It outputs every int in the container v with a Tab between them.
See [ ostream_iterator.cpp ] for a complete working example of both io-iterators.
iterator | The normal way to move across container and change things in it. |
const_iterator | The normal way to move across a container. Can not change items! |
reverse_iterator | The other way to move across container and change things in it. |
const_reverse_iterator | The other way to move across a container. Can not change items! |
Some special cases can be faster in practice: for example Hashing the search key to find an address in an array to store an item works with a short calculation and one retrieval... as long as there is spare space in the array -- say twice as many items as you have.
Never forget -- a binary search only works if the data is sorted. It slows in down to a very bad search if you always have to sort it before you search the data.
However Big_Os are easier to calculate than normal algebra -- because we can forget constants and lower order terms:
Here are some good sites: [ bigOnotation.html ] (NIST), [ Big_O_notation ] (WikiPaedia), [ LandauSymbols.html ] (history), etc. .
Typically we get the feeling that an n*n algorithm is broken on larger data sets..
Here we are usually surprised at how few data is needed to make the program do nothing for a worrying length of time.
Note: for your own classes, some containers only work if you define
bool operator<( yourClassName * the_other );
type | Operations |
---|---|
forward | ++, ==, != |
bidirectional | ++,--,==,!= |
random | +, +=, -, -=, ++,--,==,!= |
Use generate when there is a simple way to calculate a series of items in a container.
There are many more algorithms that covered in this book. See the further see [ Are there any good books on algorithms? in alg ]
You can learn how they should be coded in CSCI330.
You could look in Barjne Stroustrup's Book (Chapter 13).
To be sure what we have, you have to find the source code. On UNIX systems, like ours, you need to look in
/usr/includeYou can use ls to "LiSt" what is in this. I think you will find the relevant #include files in
ls /usr/include/c++/4.1.1/and the details in
ls /usr/include/c++/4.1.1/bitsHowever, this code is not very readable.
It would be good if you new of the existence of all the algorithms. You need to be able to use the simplest ones (no function objects or predicates).
pointer->next->previous == pointerwhenever pointer->next is not NULL.
class Person{
...
Person * mother;
Person * father;
...
friend void print_ancestors(Person * p, int gen);
...
};The rule is that once the compiler sees "class NNN" then you can declare pointers "NNN * nnn;". The NNN class is incomplete. You can not declare objects of type NNN: "NNN object" until the complete class is done.
We use can use recursion to move around and explore these structures:
void Person::print_ancestors(Person *p, int g=0)
{
if(p)
{
list_ancestors(p->mother, g+1);
list_ancestors(p->father, g+1);
cout << substr(".........", 0, g)<<*p<<endl;
}
}(unchecked code).
Address | Contents | Symbol in C++ |
---|---|---|
... | ||
1200 | 'b' | first->next |
1202 | 0 | first->next->next |
1202 | 2400 | first->next->prev |
... | ||
2400 | 'a' | first |
2401 | 1200 | first->next |
2402 | 0 | first->prev |
... |
Address | Contents | |
---|---|---|
... | ||
1200 | 'b' | |
1202 | 0 | |
1202 | 3400 | |
... | ||
2400 | 'a' | first |
2401 | 3400 | |
2402 | 0 | |
... | ||
3400 | 'c' | |
3401 | 1200 | |
3402 | 2400 | |
... |
Because: a typical rcord for a person might have several 100 bits of data and the point no more than 32bits.
Consider: which takes up more space:
QA76.76 C 1978or the book found at that place on the shelves in the library.
Which takes up more space: you or your phone number?
Name | Math | Meaning |
---|---|---|
member | x ∈ A | True if x is in A else false. |
union | A ∪ B | Elements in either A or B |
intersection | A ∩ B | Elements in both A and B |
insert | - | Afterward inserted element is in set |
remove | - | Afterward inserted element is not in set |
You can always type in code like this and add a debugging output:
cerr<< .....<< endl;at the start to see what the code does.
Use a simply linked list when you need a simple structure and program performance is more important than your time. Otherwise use the Standard Library!
Use a doubly linked list when you want reliable coded and bi-directional access.
In a complex data structure with many different links use the UML to work out whther you need a single or double linked connection. An arrow head [ Linked Data Structures in uml1b ] is the best notation for singly linked data.
For me, the coolest thing about learning matrices was replacing 25 coeficients in 5 different equations by the letter A.
In this book and in CS202 we can forget the above.... and treat matrices as two dimensional tables.
Since the book and the STL both declare iterators inside container classes the form [ container::iterator ] (STL) [ Container::Iterator ] (book) refer to the correct type of object to iterate through the Container.
* it
Each iterator refers to at most one place in a container.... sometimes it refers to NO place at all.
In the immediate future.... it would be easy for me to write an incomplete iterator class for a given container and ask you to fill in the blanks in the final....
Not on final.
Not in Labs.
You may need them in your future career.... perhaps.
ClassName::before the generic function:
template<typename T> Type_returned name(arguments){body}
For example
template<class T> void swap(T&a, T&b){ T t=a; a=b; b=t; }See [ tswap.cpp ] (note -- there is a version of swap in the std library so I don't use namespace std).
These days put helper classes and functions in the private part of the helped class.
(2) You can precompile the bodies into a ".o" object file once. Then you don't have to wait for the compiler to recompile it every time you use it.
Note: if you do split body from header.... use a tool like "make" to handle compilations.
vector< Shape *> shapes;See [ 18.html ] next class.
or this
and defined like this
or this
where
C::Nor
C < T >:: N
#define N(A) Bfrom then on any reference to N(XXX) is replaced by a copy of B with XXX replacing A. There are no rules about what B is and what XXX is. As a result macros are powerful and surprising.
If it fails to delete something then it will have a "memory leak" and it can take weeks of running the program for these to show up.
If it deletes the same piece of memory twice then this may or may not work depending on the platform. Some platforms ignore extra deletes, but others give you a segmentation fault.
This question is a powerful argument against the argument that testing can uncover all the problems with code. It shows that you may need more difficult techniques involving mathematics and logic to find all the bugs.
We will ignore them in the final.
As a rule they lead to elegant code for things that can be coded by less elegant means. They are mainly used when working with the algorithms library. I'll not mention them in the final.... but I think one may be needed in a lab.
Here is a quote from the draft C++ standard
3 [Example: If a C++ program wants to have a by-element addition of two vectors a and b containing double and put the result into a, it can do:
transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());--end example]
4 [Example: To negate every element of a:
transform(a.begin(), a.end(), a.begin(), negate<double>());The corresponding functions will inline the addition and the negation. --end example]
A way of avoiding globally defined names and collisions between different programmers.
Use namespaces when
Nearly all name spaces have a name and you can use names in it, without using two colons by writing "using namespace name".
A program can use many name spaces.... It can create them, add things to them, and refer to items in many other namespaces.
Namespaces will not be on the final.
sizeof(T)will tell you how many butes are needed to store an item of type T.
Some operating systems let you look at the bits inside a program using hexadecimal... In UNIX for example there is the command od for octal dump. By writing a simple program you can get a picture of some of the values.
To see how the operations work you really need to get the machine code manual as well as looking at the program in binary.
(word & (3 << position) )>>positionYou use '|' to set bits in word, and '^' to flip or toggle bits in a word.
See [ bitzi.cpp ]
You can write this
struct{ yada };like this:
class{ public: yada };that's all.
They are best used to defines a small set of objects with no methods, to help a useful class like a stack or queue.
Example in the lab.
Modern programming tends to use inheritance to get a similar effect.
This difference is subtle. I avoid 'do-while' because it is easier to get it wrong.
This code
do{ B } while (C)can always be re-written as
B; while(C){B}
They work by jumping to the correct case. This is often faster than executing a lot of 'if's to find the right case.
However, our Dia graphic program does use "const" instead of "<<query>>".
Use a pointer to refer to another object that is not in a container, or as an iterator to places in an array.
Symbol | Meaning |
---|---|
+ | public |
- | private |
# | protected |
Classes are boxes. In the boxes you can have a compartment for attributes (data) and operations (functions). Classes have three common links:
Here are some examples: [ Set.png ] [ SetIterator.png ]
My notes: [ uml0.html ]
[ lookup.php?search=aggreg ] (deprecated.... use an association with an arrow not an uncolored diamond).
As a rule unions are not used very much any more, except in system programs.
throw up;and so terminate.
(2) When something is thrown some part of the program should be ready to catch the result....
catch ( Yucc up){ clean(up); }
My answer: to simulate co-functions and restartable code -- a simple to use form of concurrency. [ ../cs320/ ]
Type a[SIZE];for an element
Type t;then the code might be.
for(Type *p = a; (p < a+SIZE) && (*p == t ) ; p++)
;
if(p<a+SIZE)
Found it
else
Lost it.
point -> member...which is short for
(*pointer).member...
const int SIZE=10;
vector<Enigma> v (SIZE);
for(int i = 0;i<SIZE;
{
v[i].games(i);
}
Second: a vector only grows and decreases at the end. A map can have a new value inserted at any point (and keeps the data in order).
for(int i = 0;i<SIZE;
{
v[i]=2*i+firstOddNumber;
}
As a rule you must believe that the function will work.
Just DON'T PANIC.
Mutators should not (if possible) return a value and so be declared void.
Base::fucntion_name(.....)....
Not on the final.
Not on the final!
The commonest C++ examples are iterators are public but nested in their container class. But the STL also hide some private nested classes to implement containers.
Here [ 20ex1.cpp ] is a simple example.
Also use virtual when you have multiple inheritance but only want one copy of the data to be inherited.
::operator to indicate the correct function.
deque <string> something;
map<int, string> m;
m[17]="fred";
for(map<int, string>::iterator i = m.begin(); i!=m.end(); i++) { ..... }
Lists allow you insert/delete anywhere but don't do subscripts efficiently.
In C++ -- THINK.
. . . . . . . . . ( end of section Frequently Asked Questions) <<Contents | End>>