Selectorweb.com New York
home > C++ Email
C++ short tutorial
(adapted and improved from/over  http://homepages.paradise.net.nz/milhous/ )
To download a free C++ compiler - try www.zdnet.com/downloads/
(Dev-C++ from Bloodshed may be good).
 
C++ Tutorial #1 Other pages
01 Introduction
02 Data Types
03 Enumerations
04 Type Conversions
05 Structures
06 Operators
07 Control Structures
08 Class Declarations
09 Function Declarations
10 Class Constructors
11 Function Overloading
12 Default Arguments
13 Inline Functions
14 Friend Functions
15 Arrays
16 Pointers
17 Strings
18 Reference Types
19 Memory Management
20 Operator Overloading
21 Inheritance
22 Multiple Inheritance
23 Virtual Base Classes
24 Virtual Functions
25 Constants
26 Static Keyword
27 Input/Output
28 Built in Functions
C
C++
C++ tutorial #2

01.Introduction home - top of the page - email

C++ is probably the most widely used language of them all, and still probably offers more job opportunities than any other language. All sorts of things are programmed in C++ because it is highly adaptable, allowing the programmer greater low level access to the computer. It is also Object Orientated which makes it good for writing large scale, dependable programs. Visual Basic is probably the biggest contender to C++, although some people are predicting Java will become the most dominant Object Orientated language. Even if that happened though, there would still be thousands of C++ programs out there that need maintaining.

Anyone who can program in C will have no trouble learning C++. In fact most C++ compilers will compile C code. Even if you come from something like Pascal you won't have too much trouble. C++ has the same basic structures and concepts. If you come from VB you will probably become annoyed with C++ fairly quickly. C++ allows the programmer far greater low level access to the computer than VB, but this causes as many problems as it solves.

 
02.Data types home - top of the page - email

char : char c ='A'; (some implementations allow this to be unsigned)
short: [unsigned] short s = 100; (seldom used - often the same as Integer)
integer: [unsigned] int i = 100; or i = 100U to signify unsigned (roughly -32000 >> 32000)
long: [unsigned] long l = 2000L or l = 2000UL to signify unsigned long

There are three floating point types - these are all unsigned:

float: float f = 3.168F (avoid using float unless memory conservation is necessary)
double : double d = 5.7423 (use this floating type in most instances)
long double: long double ld = 2.6534L (use this when extremely high accuracy is needed)

All these types can also be made constants.
You can declare variables anywhere in a program, not just at the start of a block like in C.
All these types can also be made static so they have a lifetime as long as the program runs. If they are not static they evaporate when their block goes out of scope.
You can also make your own data types with typedef:
    typedef char * string;
    string s = "Dane";

 
03.Enumerations home - top of the page - email

Enumerations are also possible whereby integer values can be exchanges for more meaningful values:
    enum colour {orange, gray, red};
in this example orange would take the value 0, gray 1 etc. It is also possible to assign these integer values:
    enum colour {orange = 5, gray = 2, red = 9};
These can then be used as follows:
    colour c = red;

 
04.Type Conversions home - top of the page - email

There are two types of conversion - the type you program, and the type the computer does automatically.
Computers doing things automatically is good, but it is useful to know what these conversions are:
When a value of type char or short appears in an expression such as addition they are converted to type int.

The other main time the computer converts values is when you use expressions of two or more different types, such as adding an int to a long. Basically, if a smaller type arrears in an expression with a bigger type, the smaller type is converted to the bigger type. So, an int would be converted to a long.

Some conversions need to be done explicitly. This is quite easy, for example:
    (long) i     -  given an int i, we change it to a long

Be careful though, the compiler will let you cast a number into a value it is too big for (which will corrupt the value):
    (int) 80994388;

 
05.Structures home - top of the page - email

Structures are used to group together several variables which can be of different datatypes, here is an example:

struct date {
    int day;
    int month;
    int year;
};  // remember the brackets and final semicolon.

To use this structure you declare variables of date:
    date today, yesterday;
And then use it like this:
    today.day = 22;
I have always preferred to use pointers with structures:
    date *d = new date;
    date->day = 22;
There is also a Union type in C++, but you shouldn't use it because it does bad things, and only super geeks care about saving a few bytes.

 
06.Operators home - top of the page - email

The following is a list of some of the most common operators in C++:

!=   == <  >  >=  <=  : not equal to  equal to  lesser than etc.

+  -   /  %  * :addition  subtraction  division  remainder (for integer division)  multiplication

&&  !  ||  : and  not  or

make a special point not to confuse = and ==. The later is a relational operator, as in something is equal to something else.

 
07.Control Structures home - top of the page - email

The following are the main control structures in C++:

while(condition){
    statements;
}

do{
    statements;
} while (condition)

Unlike the while statement, this do..while loop will always execute at least once. It is seldom used in programming.

for(int i = 0; i < 10; i++) {
    statements;
}

The i = 0 represents the starting value of i, the i < 10 is the ending value of i, and the i++ is the amount i is incremented with each run through the loop. Remember not to change the value of i in the statements section.

You can use the break keyword to get out of any of these loops prematurely.

if (expression) { statements; }

if (condition) { statements; } else { statements; }

if (expression1)
    statement1;
else if (expression2)
    statement2;
else
    statement3;

switch(input) {
    case value1: statements; break;
    case value2: statements; break;
    default: statements; break;
}

Remember to include the break after each section or you are screwed.

 
08.Class Declarations home - top of the page - email

Classes can either be declared with class or struct, but there is no real point of not using the class structure. The first line of a class structure for the hypothetical class person is as follows:

    class person {
           char  * name;
           int age;
       public:
           char*  getname();
           void setage(int num);
    };
 

Note: instance variables are declared - they are private by default, although they can be declared by public (though any non-lazy programmer will advise against this). Next comes the function declarations. More is said on these here, but it is important to note that they are proceeded by the keyword public:, by default they would be private. This allows them to be accessed from outside the class.

The member functions can then be constructed along the following lines:
    void person : : setage(int num) { age = num; }
More is said on declaring and using functions in later sections.
Remember to use this class from another class you will need to include "person.h" at the top of that other class.
We declare instances of this class as follows:
    person p1;
and then use call its functions as follows:
    p1.setage(18);

 
09.Functions Declarations home - top of the page - email

In C++ functions can either be member functions of a class, or, as in C, on there own. I will first explain functions on their own, though most of the same rules apply when it comes to using functions declared in a class.

The following is a basic function that accepts an integer (num), squares it, and returns the result as an integer:
    integer square(int num) {
        num = num * num;
        return num;
    }

On the first line, the first int signals the return type. If there is no return value use the void type.

The word square is the function name. The brackets indicate the argument list, in this case there is one argument, num, which is an int. All arguments (except arrays) are passed by value, so the arguments passed are changed in the called function, but retain their original values in the calling function. To find out how to pass variables by reference (so the original variable is changed by the called function) see the pointers section.

The keyword return is used to to return the value.

Calling this function is easy. Presuming we have the integer variable 'answer' that we want to store the result in, and the integer 'x' that you want to square, we call it as follows:
    answer = square(x);
if the function didn't return a value we would call it like this:
    square(x);

Declaring classes in functions is just as easy. Remember that first you must declare them in the header section of the class definition. See here to learn how to do that.  Given a class called person with the following public function declarations in the header:
    char* getname();
    void setage(int num);
we can write the functions as follows:

    char* person : : getname() { return name; }
where name is a private instance variable.

    void person : : setage(int num) { age = age + num };
once again, age is a private variable, so we access it through this public function.

Given an instance or person called p1, we access these functions as follows:
    p1.setage(18);
    char* s = p1.getname;
There isn't much to using basic functions like these. Many of the next few chapters also deal with member functions, and are useful for demonstrating what functions can do.

 
10.Class Constructors home - top of the page - email

One of the most important types of function a class will have is a constructor. These are used primarily to initialize the instance variables of a class, but they can basically do anything you want them to do. They are called once, whenever a new instance of a class is created.

The name of the function constructor is always the same as the name of the class. Like regular member functions they must be included in the header section. Given the person class used above, we could declare the constructor as follows:
    person(int a, char * s);

The argument list contain the variables we will use to initialize the class instance variables.
We then make the function as follows:
    person : : person(int a, char*  s) { age = a; name = s: }
A function can have several constructors, this is called function overloading. It can also have default functions, this is also covered in its own section.

Just as constructors are called when an instance of a class is created, a destructor is called just before it is destroyed (either by going out of scope, or with the delete keyword).

A destructor for person would be declared as follows:
    ~person();
it is then created as follows:
    person : : ~person() { statements; }
Destructors are primarily used to destroy variables created with the new keyword.

 
11.Function Overloading home - top of the page - email

Function overloading is the situation whereby the same function name has several definitions. Any function can be overloaded except destructors which don't accept arguments, but I will demonstrate on the person constructor defined above. It is currently defined as this:
    person(int a, char * s);
so when we create an instance we pass two values:
    person p1(18, "Dane");
But we may not know both the values when we create the class, we may just know the age value. We can therefore declare another constructor like this:
    person(int a);
and define it like this:
    person : : person(int a) { age = a; }
We now have two constructors for person. The program decides which one to call by looking at what arguments we pass, for instance if we declared an instance of the object with:
    person p2(20);
the second constructor would be called, because it matches the argument list of the second constructor.
We can overload the function as much as we want, we might declare another constructor that accepts no arguments:
    person();
and define it:
    person : : person() { }
It is important to remember that return values play no role here, only the argument list does. Two functions with the same name cannot differ only in their return value, because if they did, the program wouldn't not know which function to call.

Many of the benefits of function overloading can be obtained with default arguments.
Operators can also be overloaded in C++.

 
12.Default Arguments home - top of the page - email

Default arguments are good because they save time. They give the benefits of overloading without the trouble of creating separate functions for each possible argument list.  For instance, for the person class, we could declare the constructor like this:
    person(int num = 20, char * s = "Dane");
We can then define this function as below (notice the default arguments aren't included in the definition):
    person : : person(int num, char * s) {
        age = num;
        name = s;
    }

The defaults are used when no corresponding parameters are passed. If a new class was created like:
    person p1(25);
age would take the value 25, but name would get the default value.
Default values do not have to be supplied for all the arguments:
    person(int num, char * s = "Dane");
It is important to remember though, that you can't omit an argument in the argument list without also omitting all those to the right of it, otherwise the meaning would become ambiguous. This argument list is invalid:
    void triple(int a = 4, int b, int c = 9);

 
13.Inline Functions home - top of the page - email

Inline Functions are used for simple functions to increase the speed programs run at. There is a very good explanation of why inline functions increase execution speed, but it is boring, and you don't care anyway.

There is two ways to 'request' that a function be made inline (there is no guarantee the compiler will grant the request).

One way is to precede the function definition (not declaration) with the word inline.
    inline void person : : setage(int num) {age += num; }

The other way involves not giving the class a separate definition, but rather including that in the declaration:
    void setage(int num) {age += num;};

This makes things much easier, the setage function is declared and defined in one go.

 
14.Friend Functions home - top of the page - email

A function can be declared a friend of several classes. This allows us to use the same single function to access and modify the private variables of several classes. A function cannot be a member of more than one class, but it can be friends.

 
15.Arrays home - top of the page - email

Arrays are easy to declare and use in C++. This declares an array of 5 integers called arr:
    int arr[5];
Remember that arrays start at 0, so to give the first element the value 10 we write:
    arr[0] = 10;
You can also give an array values when you declare it:
    int arr[5] = {10, 20, 30, 40, 50};
You don't even need to supply all the values:
    int arr[5] = {10, 20};
static arrays are initialized to 0, but arrays like those above contain garbage until initialized.

In C++ the assignment of a whole array to another is illegal, ie. given two arrays with 10 integers each, we can't use:
    arr1 = arr2;
Instead you have to copy from arr1 to arr2 one element at a time:
    for(int i = 0, i < 10, i++) { arr1[i] = arr2[i]; }
We can have an array of class instances:
    person parray[3] = {person(10, "Jerry"), person(30, "George"), person(24, "Elaine") };
If you have multiple constructors, naturally each element can call a different constructor.

Remember, when you pass an array to a function it is passed by reference - that is, a copy is not passed, a pointer to the first element in the array is passed.

Arrays are closely connected to pointers. Anytime you need to use the name of an array to do something, you could usually also use the name of a pointer. When you declare an array like:
    int a [100];
a is really a pointer to the first element in the array a[0], that is, a = &a[0]

If we have another declaration like:
    int * p;
we can declare:
    p = a;
This allows for pointer arithmetic. If *p points to a[0] then *(p + 2) makes p point to a[2]. You can also use subtraction to move in the other direction, providing you are subtracting to a position that actually exists. With pointer arithmetic C++ takes into account the size of the data type.

You can also use the ++ and -- operators:
    *p++
moves forward one element in the array.
If p and q are both pointed to the first element in their respective arrays, and both contain 10 elements, this will copy the elements of p to q:
    for(int i = 0; i < 10, i++)  *q++ = *p++;

 
16.Pointers home - top of the page - email

Pointers are one of the most useful features of the C++ language. For more information on them look in arrays, memory management, reference types, constants, structures, virtual functions and strings in particular. This list alone tells what an important part pointers play in the language.

We declare a pointer like this:
    int * p;
P can then hold an address of an area in memory:
    int i = 10;
    p = &i;     // p equals the address of i.
We can then printout the value like this:
    cout << *p;
Or change the value of the integer p points to (ie. int i):
    *p = 30;  : the thing p points to equals 30.
Of course, you can create an area of memory for the value you want p to point to:
    p = new int;
    *p = 100;
One of the most common things pointers are used for is sending arguments to functions by reference rather than value. Except for arrays, when we pass a variable to a function we pass a copy of the variable, not the actual variable itself. This means that the variable outside the function isn't effected by any new values given to the variable inside the function. This is what we want a lot of the time, but sometimes we want a variable to be actually changed by a function.

Pointers allow us to do this because instead of sending a copy of the variable, we can instead send the memory address of the variable. The function then uses this memory address, and can alter the value stored there. This is how it can be implemented:

Suppose we have a function called change, this function accepts two integers and adds a number to them. Not only are the numbers changed inside the function, they are changed outside it as well. This is the function:
    void change( int * num1, int * num2) {
    *num1 += 10;
    *num2 += 10; };
And this is how we call it:
    int a = 20;
    int b = 20;
    change(&a, &b);
Note that when we call the function we send over two memory addresses (symbolized by &). In the function these then become pointers to the area in memory. Not only are num1 and num2 changed to 30, a and b are also changed to 30.

 
17.Strings home - top of the page - email

I have always found working with strings to be frustrating in C and C++. Of course there is no string data type, strings are just arrays of characters. They often seem to leave hard to find bugs in your programs.
A string is declared and initialized like this:
    char s[5] = "Dane";
Remember, this is a five character string, because s[4] contains the '\0' character which signified the end of a string. Don't forget this or you are in big trouble C++ will willingly let you forget the '\0' character and make you pay for it at a later date.

You can just leave it to the computer to work out how long the array is:
    char s[] = Dane";
This can then be printed out like this:
    cout << s;
or we could have just used:
    cout << "Dane";
We could also use pointers:
    char * s = "Dane";
    cout << s;

A string is always a pointer anyway.
It is an array, so its name is a pointer to the first element in the array.

There are quite a few functions that are used on strings. Most are in string.h, so remember to declare this at the top of classes that use these functions.
    strcpy is used to copy one string into another:
    char * s[5];
    strcpy(s, "Dane");
You find the length of a string with strlen:
    int l = strlen(s);
You compare two strings with strcmp:
    int cmp = strcmp(str1, str2);
It returns 0 if they are equal, a positive number if the first string is before the second in the alphabet, or a negative number if the second is first.
    strcat joins two strings together and returns a string:
    char * ret = strcat(str1, str2);

 
18.Reference Types home - top of the page - email

Reference types - work like aliases (shortcuts in Windows terminology). They aren't really a necessary part of the language, they are used to make it easier to send elements to a function by reference rather than value. This is how they work.
Suppose we have an integer variable:
    int k = 20;
we can declare a reference type that references it:
    int& r = k;
r is now an alias for k. If we change the value of the one, we change the value of the other because they both reference the same area of memory.

We can also make a reference type that doesn't refer to another variable:
   int&w = 20;
This creates an integer object and gives it the value of 20.
References are then usually used to pass arguments by reference. If there is a function that takes two references:
    void two(int& a, int&b);
we can call it with:
    two(w, r);
because w and r are reference types. This just makes things a bit simpler when sending values by reference.

 
19.Memory Management home - top of the page - email

Memory management is very easy is C++, the only keywords you need to remember are new and delete.
The new operator is used to create objects of any data type. These objects then stay in existence until they are explicitly destroyed with the delete operator.
Suppose we had declared a pointer to an integer:
    int * i;
This can either point to an existing integer, or we can create an area of memory for it to store its own integer:
    i = new int;
We can then give this area a value:
    *i = 200;
We can also create instances of classes like this:
    person * p1;
    p1 = new person(20, "Michael");
We can then use the -> operator to use this object:
    p1->setage(33);
We can also create an array this way:
    int * a = new int[100];
this creates an array of 150 integers with a pointing to the first element, and a[2] pointing to the third element.
When you don't need the data object anymore it is easy to destroy by using the delete operator.
    delete i;
if we are destroying a class object:
    delete p1;
the destructor is called before it is destroyed.
The one main complication arises when a memory area to be destroyed contains an array of classes which have destructors. Other arrays can be deleted simply with:
    delete a;
but if it is an array of objects with constructors the delete operator needs to know how many destructors need to be called. There are a couple of main ways of doing this, and some compilers will not support the second method below. Supposing ao points to an array of 100 objects, the first method is:
    delete [100] ao;
On most modern compilers you do not need to specify the number of elements the array holds:
    delete [] ao;
but the empty brackets are still needed.

 
20.Operator Overloading home - top of the page - email

int a,b,c;
Mytype   A,B,C;
....
c = a+b;  c = 1+a;  cout << a;  // valid statements
C = A + B;  C = 1 + A;  cout << A; // compiler will complain.

As we see, those operations (addition and ostream)  are not defined for those objects.
So we can define them.
We can do this by defining so called "operator functions" ( in this case call it operator+()  and operator<<() ) which will tell the compiler what to do (how to add objects or nubmer and an objects). For example:
Mytype operator+ (Mytype N1, Mytype N2) {
      Mytype T;
      T.n = N1.n + N2.n;
      return T;
}

This is called operator overloading.

Similarly we can define operator functions to overload most of other operations ( operator/    opeartor%    operator*    operator- S, even   operator= ).
Here is an example for the case of the above 2 operators:  operator+    and   operator<< .
Note that we define operator function here with '&' - so that they return a reference to an object.  even
Also note, that we make them friends so that they have access to private numbers.
#include <iostream.h>

class number {
      int n;    // private number;
   public:
      number { n=1;}
      friend number& operator+ (number&, number&);
      friend ostream& operator<< (ostream&, number&);
};

number T;    // Temporary object (global)

number& operator+ (number&  N1, number& N2) {
      T.n = N1.n + N2.n;
      return T;
}

ostream&  operator<<  (ostream& Cout, number& N) {
      Cout << ' ' << N.n << ' ';
      return Cout;
}

void main() {
      number X, Y, Z = X+Y;
      cout << X << '+' << Y << '='  << Z;   // 1 + 1 = 2;
}


 
21.Inheritance home - top of the page - email

Inheritance allows a new class to be created by extending a class you have already created. This can save a lot of time and effort. Any class you derive from a base class can itself then become a base class from which you can derive more classes.

This section deals with single inheritance (each derived class inherits the properties of one base class). Multiple inheritance is dealt with in the next section.
Suppose we had created a class to hold the details of a bank account. This account is called account and defined as follows :
class account {
    double balance; //the balance of the account
    double rate; //the interest rate
public:
    account(double b, double r);
    void deposit(double amt);
    double withdraw(double amt);
    double getbalance();
};

It is fairly obvious how these would be implemented :
account::account(double b, rouble r)  {
    balance = b;
    rate = r;
}

double account::getbalance()  {
    return balance;
}

etc. etc.

If we were writing a program dealing with bank accounts we might decide no one just has an account. They have a savings account or a check account or a time deposit account. All these accounts will have things in common with each other, but they will also have things which are different from each other.

To deal with this we could make one generic class called account that implemented the things all the classes have in common. Then we could extend this implementation for each type of account by creating a new class that inherited all these features, but also added some features unique to it.

In the case of accounts we might decide that the things all accounts have in common is that they have a balance, that you can deposit money, and that you can check your balance : we can define and implement it like this:
class account {
   protected:
      double balance; //the balance of the account
   public:
      account(double b) {balance = b;}
      void deposit(double amt) {balance += amt;}
      double getbalance() {return balance;}
};

The important thing to notice is that the instance variable balance is protected. In previous examples the instance  variables were defined as private. The reason we need to make it protected is so that the functions in classes that inherit account can access it. In all other respects it is still private.

Of course you may not want the functions in a derived class to have access to the instance variables of their base class, in which case you can still declare them as private.

Now we can create a class called savings_account that inherits all the instance variables and functions of account, but adds some of its own.
class savings_account : public account {
   protected:
      double rate; //the rate of interest in the savings account
   public:
      savings_account(double b, double r);
      double compound(); //computes the rate of interest
      double withdraw(double amt);
};

We have made rate a protected variable in case we derive classes from savings_account.

Also note that account has been inherited as public account. Use public to ensure that member functions of the base class are available to users of the derived class. The alternative is private but you will seldom want to do this, so don't worry too much about it.

You may have noticed that savings_account will now have two instance variables - balance which is inherited from account, and rate which is declared in savings_account. Because of this we will want to call the constructors of both classes to initialize these two variables. This can easily be done like this :
savings_account::savings_account(double b, double r) : account(b)  {
    rate = r;
}

The constructor of savings_account accepts both the variables needed to initialize an instance of the class, but it sends b on to the account constructor, and only deals directly with the r variable. This is signaled by the :account(b) on the first line. You can send away multiple arguments, just as long as the constructor in the base class will know what to do with them. If the account constructor took no arguments there would be no need to call it directly, although the program will still call it with no arguments. The constructor for the base class is actually called before the constructor of the derived class.

The other functions of savings_account have straightforward implementations.

Now if we create an instance of savings_account it can call not only the member functions of savings_account but also all those in account.

It is also possible to redefine functions in a derived class. Lets presume that the bank decides to charge people a fee for depositing money into their savings account (my bank is about at this stage now). The implementation of deposit in account is not sufficient because it only deposits the amount the user requests.

We could redefine the function in savings_account like this:

 void deposit(double amt);

and then implement it like this:
void deposit(double amt) {
    balance += amt;
    balance -= 1.00;
}

Now when an instance of savings_account calls deposit, it calls the function as defined in savings_account rather than the one defined in account.

We can also derive new classes from savings_account. Suppose we decide that a time deposit account has all the features that a savings account has, but also a few more. We might define it like this :
class time_account : public savings_account {
   protected:
      double funds_avaliable;
   public:
      time_account(double b, double r, double f);
      double compound();
      double get_avaliable_funds() {return avaliable_funds;}
};

This new class has its own constructor, a function to show the available funds, and also a function that redefines the compound function defined in savings_account.

The most interesting thing to consider is the constructor. It might be declared like this:
time_account::time_account(double b, double r, double f) : savings_account(b, r) 
{
    funds_avaliable = f;
}

The constructor uses one of the variables sent to it, but the other two are sent away to savings_account to initialize that class. Of course we also know that one of those will in turn be sent to account but we don't need to know this here - just as long as savings_account knows it.

Other issues relating to inheritance are dealt with in other sections, but this introduction covers 90% of the things you will need to know for most situations.

 
22.Multiple Inheritance home - top of the page - email

Multiple inheritance may not be such a good idea. If you can avoid it you probably should, but it is good to know how to do it.
Example: a class clock_calendar  derived from 2 classes: clock & calendar:
class clock {
   protected:
       int hr;
       int min;
   public:
      clock(int h, int m);
      void advance();
      void set_clock(int h, int m);
      void read_clock(int& h, int&m); 
};

class calendar {
   protected:
      int mt;
      int day;
      int yr
   public:
      calendar(int mt, int day, int yr);
      void advance();
      void set_calendar(int mt, int day, int yr);
      void read_calendar(int& mt, int&day, int& yr); 
};

// We can then create the clock_calendar class:

class clock_calendar : public clock, public calendar {
   public:
      clock_calendar(int mt, int day, int yr, int h, int m);
      void advance();
};

The constructor will then look like this - note that it calls the two existing constructors:

clock_calendar : : clock_calendar
    ( int mt, int day, int yr, int h, int m)
    : calendar(mt, day, yr), clock(h, m) { }

All the member functions except advance are inherited, and all work exactly the same, although any could be overwritten if clock_calendar chose to define them. Advance must be overwritten, because if it was called from class_calendar C++ wouldn't know whether to call it from clock or calendar.

There would be a way around it if you insisted on not redefining it:
   clock_calendar cc;
   cc.clock : : advance();
   cc.calendar : : advance();
Both would work. Unfortunately if you try to program in this way you will forget the full phrase from time to time, it's inevitable.

 
23.Virtual Base Classes home - top of the page - email

You may never need to use Virtual Base Classes - but there is no harm in knowing what they are for, just in case the need ever arises.
Consider the following scenario:
The base class for a program is Grandparent. This has two Classes derived from it:
   class Parent_husband : public Grandparent
   class Parent_wife : public Grandparent
We then have another class, Child which has multiple inheritance from both Parent_husband and Parent_wife:
   class Child : public Parent_husband, public Parent_wife
A problem arises here. Child not only inherits the characteristics of the two Parent classes, but also, from these, the characteristic of Grandparent. The problem is, it is inheriting Grandparent twice, once from Parent_husband, and once from Parent_wife.

To avoid this problem the intermediate base classes (the two parent classes) must specify Grandparent to be a virtual base class. Only one set of members will be inherited from a virtual base class, no matter how many times it occurs in the inheritance chain. This is very easy to do, simply change the declaration to this:
   class Parent_husband : virtual public Grandparent
   class Parent_wife : virtual public Grandparent
Seeing the problem is the difficult part, solving it is very easy.

 
24.Virtual Functions home - top of the page - email

Virtual function allow for polymorphism, one of the great buzz words in Object Orientated programming. What this means is that objects in different classes can respond to the exact same message in different ways. Suppose a class child is derived from a class parent .
A pointer to a parent class:
   parent * p;
can be also used to point to an instance of child:
   p = &c1;
presuming c1 was an instance of the child class.

Lets suppose that class parent had two functions, one virtual, the other not:
   virtual void vf() {cout << "This is a virtual function";}
   void nvf() {cout << "This is not a virtual function";}

Class child redefines these two functions - but note the virtual keyword is NOT used:

class child : public parent {
   ...
  public:
   void vf() {cout << "This is a virtual function of child";}
   void nvf() {cout << "This is not a virtual function of child";}
};

When p is pointing to an instance of parent, then
  p->vf();
  p->nvf();
are calls to parent's functions (as you would expect).

But if we point this (parent type) pointer it to a child:
   p = &c1;
Now
   p->vf();  // will point to a function in a child, because it is a virtual function
   p->nvf(); // still points to the function in a parent.

With a virtual function, the class of the object pointed to determined the function definition used. If p points to an instance of parent the parent functions are used, but if p is changed to point to an instance of child, the child functions are used.

 
25.Constants home - top of the page - email

Constants can also be declared in C++. The basic form is this:
  const int year = 2000;

If no type is included int is presumed, so we could actually declare this:
  const year = 2000;

Objects and functions can also be constants. An object is declared constant like this:
  const person p1(22, "Dane");

On the whole this means nothing about p1 can be changed, so statements like:
  p1.setage(20);

would be illegal, and rightly so. But statements like:
  cout << p1.getage();

is also illegal, which is stupid, because it isn't changing p1 in any way.
The way around this is to declare getage as a const in both its declaration and definition:
  int getage() const;
  int person : : getage() const { return age; }

If getage was an inline function it would be changed like this:
  int getage() const {return age;}

Pointers can also be made constants. This can mean two different things, the first is this:
  int k = 25;
  int * const p = &k;  // const pointer

This means p must always point to k, but the value of k can be changed:
  *p = 40;

The other way is this:
  int k = 25;
  const int * p = &k;  // const int value
This means that p can point to a different location, but we can change the value of k.
So we cannot use expressions like
  *p = 40;
but we can change what p points to:
  p = &newint;
In effect this is a read only pointer. It can be set to point to any area of memory, but it can't change the value stored there.

 
26.Static Keyword home - top of the page - email

The static keyword is used in many different situations, but it always is used to affect scope.
A static data object stays in existence until the end of the program. This is opposed to normal automatic objects are destroyed when they go out of scope. They are declared like this:

static int i = 100;

Note: if a static variable isn't initialized, the compiler initializes it to 0.
Note: if you declare it inside a block it can still only be referred to inside that block, although it isn't destroyed when the block goes out of scope.

A class can also create class variables with the static keyword. These data objects are associated with the class itself rather than any instance of the class. No matter how many instances of the class are created, there is only one of these data objects. Every instance of the class accesses the same variable. They can be declared like this:

class example {
  int k;
  static int m;
  static int n;
public:
  int getk() {return k;}
  static void setm(int num) {m = num;}
};

Both m and n are static variables, only one set of them can ever exist in the program. They have not been created yet though. They both must be defined in the source file like this:

int example : : m;
int example : : n = 10;

Any function can manipulate m and n, but you can make special static functions that can only access static members: setm is an example. The great thing about these functions is that they can be called even when no instance of the class exists. We call them like this:

example.setm(20);

 
27.Input/Output home - top of the page - email

User input/output:
cin>> n;
cout << somthing << somthing <<endl;
 
// file p2.cpp
 #include <iostream.h>

 const int ii = 5; // const will not allow to change it

 int main() {
   int n;
   cout<<"Hello" << ii << "Dear" 
              "Friend" << endl;
   cout<<"Please\nPlease enter a number: ";
   cin>> n;
   cout<<"You entered: "<< n <<endl;
   cout<<"Squared:   "<< n*n <<endl;

  char string[256];   //A nice long string
  cout<<"Please enter a long string: ";
  cin.getline(string, 256, '\n'); //The user input goes into string
  cout<<"Your long string was:"<<endl<<string;

   return 0;
 }

File read/write:
    ifstream a_file("test.txt");   // read
    ofstream a_file("test.txt");   // write

Those functions can accept optional 2nd argument, for example:
    ifstream a_file("test.txt", ios::app);   // open for appending

Possible values:
    ios::app -- Opens the file, and allows additions at the end
    ios::ate -- Opens the file, but allows additions anywhere
    ios::trunc -- Deletes everything in the file
    ios::nocreate -- Does not open if the file must be created
    ios::noreplace -- Does not open if the file already exists

Example: read text file and output it on the screen:
ifstream my_in("example.txt"); 
my_in >> str; 
cout<<str; 
my_in.close(); 

 
28.Built in Functions home - top of the page - email

For the string functions, go to the strings section.
A lot of the other most useful built in functions are in the math.h class:
float f = sqrt(9);
float f = sin(90)  // same applied for tan() and cos().
pow(x, z)  // returns x to the power of y.
log(x) and log10(x)
abs(x)  //: returns absolute of x