This text is aimed at C users who wish to learn C++. It is also interesting for experienced C++ users who leaved out some features of the language. The possibilities of C++ are briefly enunciated and illustrated. When you will try to use them for your own programs you will encounter a lot of problems and compilation errors. Come back to this text and look carefully at the examples. Make use of the help files of your development environment. Do not hesitate to copy the examples from this text and paste them inside your development environment in order to test and modify them.
You can use / / to type a remark :
#include // This library is often used void main () // The program's main routine. { double a; // Declaration of variable a. a = 456; a = a + a * 21.5 / 100; // A calculation. cout << a; // Display the content of a. }
#include void main() { int a; // a is an integer variable char s [100]; // s points to a sring of 99 characters cout << "This is a sample program." << endl; cout << endl; // Line feed (end of line) cout << "Type your age : "; cin >> a; cout << "Type your name : "; cin >> s; cout << endl; cout << "Hello " << s << " you're " << a << " old." << endl; cout << endl << endl << "Bye !" << endl; }
#include void main () { double a; cout << "Hello, this is a test program." << endl; cout << "Type parameter a : "; cin >> a; a = (a + 1) / 2; double c; c = a * 5 + 1; cout << "c contains : " << c << endl; int i, j; i = 0; j = i + 1; cout << "j contains : " << j << endl; }
#include void main () { double a = 12 * 3.25; double b = a + 1.112; cout << "a contains : " << a << endl; cout << "b contains : " << b << endl; a = a * 2 + b; double c = a + b * a; cout << "c contains : " << c << endl; }
#include void main() { double a; cout << "Type a number : "; cin >> a; { int a = 1; a = a * 10 + 4; cout << "Local number : " << a << endl; } cout << "You typed : " << a << endl; }
#include void main () { for (int i = 0; i < 4; i++) { cout << i << endl; } cout << "i contains : " << i << endl; for (i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) // we're between { // previous for's hooks cout << i; } cout << endl; } }
#include double a = 128; void main () { double a = 256; cout << "Local a : " << a << endl; cout << "Global a : " << ::a << endl; }
#include void main () { double a = 3.1415927; double &b = a; // b IS a b = 89; cout << "a contains : " << a << endl; // Displays 89. }
Everything is said on the declaration line of b. Reference b and variable a are married on that line and nothing will separate them.
References can be used to allow a function to modify a calling variable :
#include void change (double &r, double s) { r = 100; s = 200; } void main () { double k, m; k = 3; m = 4; change (k, m); cout << k << ", " << m << endl; // Displays 100, 4. }
#include void change (double *r, double s) { *r = 100; s = 200; } void main () { double k, m; k = 3; m = 4; change (&k, m); cout << k << ", " << m << endl; // Displays 100, 4. }
#include double &biggest (double &r, double &s) { if (r > s) return r; else return s; } void main () { double k = 3; double m = 7; cout << "k : " << k << endl; cout << "m : " << m << endl; cout << endl; biggest (k, m) = 10; cout << "k : " << k << endl; cout << "m : " << m << endl; cout << endl; biggest (k, m) ++; cout << "k : " << k << endl; cout << "m : " << m << endl; cout << endl; }
#include double *biggest (double *r, double *r) { if (*r > *s) return r; else return s; } void main () { double k = 3; double m = 7; cout << "k : " << k << endl; cout << "m : " << m << endl; cout << endl; (*(biggest (&k, &m))) = 10; cout << "k : " << k << endl; cout << "m : " << m << endl; cout << endl; (*(biggest (&k, &m))) ++; cout << "k : " << k << endl; cout << "m : " << m << endl; cout << endl; }
#include double *silly_function () // This function returns a pointer to a double { static double r = 342; return &r; } void main() { double *a; a = silly_function(); double &b = *a; // Now b IS the double towards which a points ! b += 1; // Great ! b = b * b; // No need to write *a everywhere ! b += 4; cout << "Content of *a, b, r : " << b << endl; }
#include #include inline double hypothenuse (double a, double b) { return sqrt (a * a + b * b); } void main () { double k = 6, m = 9; // Next two lines produce exactly the same code : cout << hypothenuse (k, m) << endl; cout << sqrt (k * k + m * m) << endl; }
#include #include void main () { int a, b; cout << "Type a number : "; cin >> a; cout << endl; try { if (a > 100) throw 100; if (a < 10) throw 10; throw a / 3; } catch (int result) { cout << "Result is : " << result << endl; b = result + 1; } cout << "b contains : " << b << endl; cout << endl; // another example of exception use : char zero[] = "zero"; char pair[] = "pair"; char notprime[] = "not prime"; char prime[] = "prime"; try { if (a == 0) throw zero; if ((a / 2) * 2 == a) throw pair; for (int i = 3; i <= sqrt (a); i++) { if ((a / i) * i == a) throw notprime; } throw prime; } catch (char *conclusion) { cout << "The number you typed is "<< conclusion << endl; } cout << endl; }
#include double test (double a, double b = 7) { return a - b; } void main () { cout << test (14, 5) << endl; cout << test (14) << endl; }
#include double test (double a, double b) { return a + b; } int test (int a, int b) { return a - b; } void main () { double m = 5, n = 3; int k = 5, p = 3; cout << test(m, n) << " , " << test(k, p) << endl; }
#include struct vector { double x; double y; }; vector operator * (double a, vector b) { vector r; r.x = a * b.x; r.y = a * b.y; return r; } void main () { vector k, m; // No need to type "struct vector" k.x = 2; // Keep cool, soon you'll be able k.y = -1; // to write k = vector (45, -4). m = 3.1415927 * k; // Magic ! cout << "(" << m.x << ", " << m.y << ")" << endl; }
The operation cout << is an overload of the binary shift of integers. That way the << symbol is used a completely different way. It is thus possible to define the output of vectors :
#include struct vector { double x; double y; }; ostream& operator << (ostream& o, vector a) { o << "(" << a.x << ", " << a.y << ")"; return o; } void main () { vector a; a.x = 35; a.y = 23; cout << a << endl; }
#include #include void main () { double *d; // d is a variable whose purpose // is to contain the address of a // zone where a double is located d = new double; // new allocates a zone of memory // large enough to contain a double // and returns its address. // That address is stored in d. *d = 45.3; // The number 45.3 is stored // inside the memory zone // whose address is given by d. cout << "Type a number : "; cin >> *d; *d = *d + 5; cout << "Result : " << *d << endl; delete (d); // delete deallocates the // zone of memory whose address // is given by pointer d. // Now we can no more use that zone. d = new double[15]; // allocates a zone for an array // of 15 doubles d[0] = 4456; d[1] = d[0] +567; cout << "Content of d[1] : " << d[1] << endl; delete (d); int n = 30; d = new double[n]; // new can be used to allocate an // array of random size. for (int i = 0; i < n; i++) { d[i] = i; } delete (d); char *s; s = new char[100]; strcpy (s, "Hello !"); cout << s << endl; delete (s); }
#include class vector { public: double x; double y; double surface () { double s; s = x * y; if (s < 0) s = -s; return s; } }; void main(void) { vector a; a.x = 3; a.y = 4; cout << "The surface of a : " << a.surface() << endl; }
Just like a function, a method can be an overload of any C++ operator, have any number of parameters (yet one parameter is always implicit : the instance it acts upon), return any type of parameter, or return no parameter at all.
A method is allowed to change the variables of the instance it is acting upon :
#include class vector { public: double x; double y; vector its_oposite() { vector r; r.x = -x; r.y = -y; return r; } void be_oposited() { x = -x; y = -y; } void be_calculated (double a, double b, double c, double d) { x = a - c; y = b - d; } vector operator * (double a) { vector r; r.x = x * a; r.y = y * a; return r; } }; void main (void) { vector a, b; a.x = 3; b.y = 5; b = a.its_oposite(); cout << "Vector a : " << a.x << ", " << a.y << endl; cout << "Vector b : " << b.x << ", " << b.y << endl; b.be_oposited(); cout << "Vector b : " << b.x << ", " << b.y << endl; a.be_calculated (7, 8, 3, 2); cout << "Vector a : " << a.x << ", " << a.y << endl; a = b * 2; cout << "Vector a : " << a.x << ", " << a.y << endl; a = b.its_oposite() * 2; cout << "Vector a : " << a.x << ", " << a.y << endl; cout << "x of oposite of a : " << a.its_oposite().x << endl; }
The constructor will initialize the variables of the instance, do some calculation, allocate some memory for the instance, output some text... whatever is needed.
Here is an example of a class definition with two overloaded constructors.
#include class vector { public: double x; double y; vector () // same name as class { x = 0; y = 0; } vector (double a, double b) { x = a; y = b; } }; void main () { vector k; // vector () is called cout << "vector k : " << k.x << ", " << k.y << endl << endl; vector m (45, 2); // vector (double, double) is called cout << "vector m : " << m.x << ", " << m.y << endl << endl; k = vector (23, 2); // vector created, copied to k, then erased cout << "vector k : " << k.x << ", " << k.y << endl << endl; }
#include class vector { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } }; void main () { vector k; cout << "vector k : " << k.x << ", " << k.y << endl << endl; vector m (45, 2); cout << "vector m : " << m.x << ", " << m.y << endl << endl; vector p (3); cout << "vector p : " << p.x << ", " << p.y << endl << endl; }
#include #include class person { public: char *name; int age; person (char *n = "no name", int a = 0) { name = new char[100]; // better than malloc ! strcpy (name, n); age = a; cout << "Instance initialized, 100 bytes allocated" << endl; } ~person () // The destructor { delete (name); // instead of free ! cout << "Instance going to be deleted, 100 bytes freed" << endl; } }; void main () { cout << "Hello !" << endl << endl; person a; cout << a.name << ", age " << a.age << endl << endl; person b ("John"); cout << b.name << ", age " << b.age << endl << endl; b.age = 21; cout << b.name << ", age " << b.age << endl << endl; person c ("Miki", 45); cout << c.name << ", age " << c.age << endl << endl; cout << "Bye !" << endl << endl; }
#include #include class person { public: char *name; int age; person (char *n = "no name", int a = 0) { name = new char[100]; strcpy (name, n); age = a; } person (person &s) // The COPY CONSTRUCTOR { strcpy (name, s.name); age = s.age; } ~person () { delete (name); } }; void main () { person p; cout << p.name << ", age " << p.age << endl << endl; person k ("John", 56); cout << k.name << ", age " << k.age << endl << endl; p = k; cout << p.name << ", age " << p.age << endl << endl; p = person ("Bob", 10); cout << p.name << ", age " << p.age << endl << endl; }
If a method cannot be inline, if you do not want it to be inline or if you want the class definition contain the minimum of information, then you must just put the prototype of the method inside the class and define the method below the class :
#include class vector { public: double x; double y; double surface(); // The ; and no {} shows it is a prototype }; double vector::surface() { double s = 0; for (double i = 0; i < x; i++) { s = s + y; } return s; } void main () { vector k; k.x = 4; k.y = 5; cout << "Surface : " << k.surface() << endl; }
#include #include class vector { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } double module() { return sqrt (x * x + y * y); } void set_length (double a = 1) { double length; length = this->module(); x = x / length * a; y = y / length * a; } }; void main () { vector c (3, 5); cout << "The module of vector c : " << c.module() << endl; c.set_length(2); // Transforms c in a vector of size 2. cout << "The module of vector c : " << c.module() << endl; c.set_length(); // Transforms b in an unitary vector. cout << "The module of vector c : " << c.module() << endl; }
#include #include class vector { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } double module () { return sqrt (x * x + y * y); } }; void main () { vector s[1000]; vector t[3] = {vector(4, 5), vector(5, 5), vector(2, 4)}; s[23] = t[2]; cout << t[0].module() << endl; }
#include #include class vector { public: double x; double y; vector (double = 0, double = 0); vector operator + (vector); vector operator - (vector); vector operator - (); vector operator * (double a); double module(); void set_length (double = 1); }; vector::vector (double a, double b) { x = a; y = b; } vector vector::operator + (vector a) { return vector (x + a.x, y + a.y); } vector vector::operator - (vector a) { return vector (x - a.x, y - a.y); } vector vector::operator - () { return vector (-x, -y); } vector vector::operator * (double a) { return vector (x * a, y * a); } double vector::module() { return sqrt (x * x + y * y); } void vector::set_length (double a) { double length = this->module(); x = x / length * a; y = y / length * a; } ostream& operator << (ostream& o, vector a) { o << "(" << a.x << ", " << a.y << ")"; return o; } void main () { vector a; vector b; vector c (3, 5); a = c * 3; a = b + c; c = b - c + a + (b - a) * 7; c = -c; cout << "The module of vector c : " << c.module() << endl; cout << "The content of vector a : " << a << endl; cout << "The oposite of vector a : " << -a << endl; c.set_length(2); // Transforms c in a vector of size 2. a = vector (56, -3); b = vector (7, c.y); b.set_length(); // Transforms b in an unitary vector. cout << "The content of vector b : " << b << endl; double k; k = vector(1, 1).module(); // k will contain 1.4142. cout << "k contains : " << k << endl; }
vector operator + (vector a, vector b) { return vector (a.x + b.x, a.y + b.y); }
vector operator * (double a, vector b) { return vector (a * b.x, a * b.y); }
#include #include class vector { public: double x; double y; vector (double = 0, double = 0); vector operator + (vector); vector operator - (vector); vector operator - (); vector operator * (double); double module(); void set_length (double = 1); }; vector::vector (double a, double b) { x = a; y = b; } vector vector::operator + (vector a) { return vector (x + a.x, y + a.y); } vector vector::operator - (vector a) { return vector (x - a.x, y - a.y); } vector vector::operator - () { return vector (-x, -y); } vector vector::operator * (double a) { return vector (a * x, a * y); } double vector::module() { return sqrt (x * x + y * y); } void vector::set_length (double a) { vector &the_vector = *this; double length = the_vector.module(); x = x / length * a; y = y / length * a; } ostream& operator << (ostream& o, vector a) { o << "(" << a.x << ", " << a.y << ")"; return o; } void main () { vector c (3, 5); vector *r; // r is a pointer to a vector. r = new vector; // new allocates the memory necessary cout << *r << endl; // to hold a vectors' variable, // calls the constructor who will // initialize it to 0, 0. Then finally // new returns the address of the vector. r->x = 94; r->y = 345; cout << *r << endl; *r = vector (94, 343); cout << *r << endl; *r = *r - c; r->set_length(3); cout << *r << endl; *r = (-c * 3 + -*r * 4) * 5; cout << *r << endl; delete (r); // Calls the vector destructor then // frees the memory. r = &c; // r points towards vector c cout << *r << endl; r = new vector (78, 345); // Creates a new vector. cout << *r << endl; // The constructor will initialise // the vector's x and y at 78 and 345 cout << "x component of r : " << r->x << endl; cout << "x component of r : " << (*r).x << endl; delete (r); r = new vector[4]; // creates an array of 4 vectors r[3] = vector (4, 5); cout << r[3].module() << endl; delete (r); // deletes the array int n = 5; r = new vector[n]; // Cute ! r[1] = vector (432, 3); cout << r[1] << endl; delete (r); }
#include class vector { public: double x; double y; static int count; vector (double a = 0, double b = 0) { x = a; y = b; count = count + 1; } ~vector() { count = count - 1; } }; void main () { vector::count = 0; cout << "Number of vectors :" << endl; vector a; cout << vector::count << endl; vector b; cout << vector::count << endl; vector *r, *u; r = new vector; cout << vector::count << endl; u = new vector; cout << a.count << endl; delete (r); cout << vector::count << endl; delete (u); cout << b.count << endl; }
#include class vector { public: double x; double y; const double pi = 3.1415927; vector (double a = 0, double b = 0) { x = a; y = b; } double cilinder_volume () { return x * x / 4 * pi * y; } }; void main(void) { cout << "The value of pi : " << vector::pi << endl << endl; vector k (3, 4); cout << "Result : " << k.cilinder_volume() << endl; }
#include #include class vector { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } double module() { return sqrt (x*x + y*y); } double surface() { return x * y; } }; class trivector : public vector // trivector is derived from vector { public: double z; // added to x and y from vector trivector (double m=0, double n=0, double p=0) : vector (m, n) { z = p; // Vector constructor will } // be called before trivector // constructor, with parameters // m and n. trivector (vector a) // What to do if a vector is { // cast to a trivector x = a.x; y = a.y; z = 0; } double module () // define module() for trivector { return sqrt (x*x + y*y + z*z); } double volume () { return this->surface() * z; // or x * y * z } }; void main() { vector a (4, 5); trivector b (1, 2, 3); cout << "a (4, 5) b (1, 2, 3) *r = b" << endl << endl; cout << "Surface of a : " << a.surface() << endl; cout << "Volume of b : " << b.volume() << endl; cout << "Surface of base of b : " << b.surface() << endl; cout << "Module of a : " << a.module() << endl; cout << "Module of b : " << b.module() << endl; cout << "Module of base of b : " << b.vector::module() << endl; trivector k; k = a; // thanks to trivector(vector) definition // copy of x and y, k.z = 0 vector j; j = b; // copy of x and y. b.z leaved out vector *r; r = &b; cout << "Surface of r : " << r->surface() << endl; cout << "Module of r : " << r->module() << endl; }
(If at least one of the methods of the base class is virtual then a "header" of 4 bytes is added to every instance of the classes. This allows the program to determine towards what a vector actually points.)
#include #include class vector { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } virtual double module() { return sqrt (x*x + y*y); } }; class trivector : public vector { public: double z; trivector (double m = 0, double n = 0, double p = 0) { x = m; // Just for the game, y = n; // here I do not call the vector z = p; // constructor and I make the } // trivector constructor do the // whole job. Same result. double module () { return sqrt (x*x + y*y + z*z); } }; void test (vector &k) { cout << "Test result : " << k.module() << endl; } void main() { vector a (4, 5); trivector b (1, 2, 3); cout << "a (4, 5) b (1, 2, 3)" << endl << endl; vector *r; r = &a; cout << "module of vector a : " << r->module() << endl; r = &b; cout << "module of trivector b : " << r->module() << endl; test (a); test (b); vector &s = b; cout << "module of trivector b : " << s.module() << endl; }
#include #include class vector { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } double surface() { return fabs (x * y); } }; class number { public: double z; number (double a) { z = a; } int is_negative () { if (z < 0) return 1; else return 0; } }; class trivector : public vector, public number { public: trivector(double a=0, double b=0, double c=0) : vector(a,b), number(c) { } // The trivector constructor calls the vector // constructor, then the number constructor, // and in this example does nothing more. double volume() { return fabs (x * y * z); } }; void main() { trivector a(2, 3, -4); cout << a.volume() << endl; cout << a.surface() << endl; cout << a.is_negative() << endl; }
Suppose you define a base class with no variables. It makes no sense to use instances of that class inside your program. But you write a function whose purpose is to sort instances of that class. Well, that function will be able to sort any types of objects provided they belong to a class derived from that base class ! The only condition is that inside every derived class definition all methods the sort function needs are correctly defined :
#include #include class octopus { public : virtual double module() = 0; // = 0 implies function is not // defined. This makes instances // of this class cannot be declared. }; double biggest_module (octopus &a, octopus &b, octopus &c) { double r = a.module(); if (b.module() > r) r = b.module(); if (c.module() > r) r = c.module(); return r; } class vector : public octopus { public: double x; double y; vector (double a = 0, double b = 0) { x = a; y = b; } double module() { return sqrt (x * x + y * y); } }; class number : public octopus { public: double n; number (double a = 0) { n = a; } double module() { if (n >= 0) return n; else return -n; } }; void main () { vector k (1,2), m (6,7), n (100, 0); number p (5), q (-3), r (-150); cout << biggest_module (k, m, n) << endl; cout << biggest_module (p, q, r) << endl; cout << biggest_module (p, q, n) << endl; }
class octopus { virtual double module() = 0; }; class cuttlefish { virtual int test() = 0; }; class vector : public octopus, public cuttlefish { double x; double y; double module () { return sqrt (x * x + y * y); } int test () { if (x > y) return 1; else return 0; } }
If you want them to be accessible only to methods of the class AND to methods of derived classes then you must put the keyword protected: above them.
If you want variables or methods be accessible ONLY to methods of the class then you must put the keyword private: above them.
The fact variables or methods are declared private or protected means no function external to the class may access or use them. That's ENCAPSULATION. If you want to give to a specific function the right to access those variables and methods then you must include that function's prototype inside the class definition, preceded by the keyword friend.
Now let's talk about input/output. In C++ that's a very broad subject.
Here is a program that writes to a file :
#include #include void main () { fstream f; f.open("c:\\test.txt", ios::out); f << "This is a text output to a file." << endl; double a = 345; f << "A number : " << a << endl; f.close(); }
#include #include void main () { fstream f; char c; cout << "What's inside the test.txt file from"; cout << "the C: hard disk root " << endl; cout << endl; f.open("c:\\test.txt", ios::in); while (! f.eof() ) { f.get(c); // Or c = f.get() cout << c; } f.close(); }
Here is a program that writes inside a character array :
#include #include #include #include void main () { char a[1024]; ostrstream b(a, 1024); b.seekp(0); // Start from first char. b << "2 + 2 = " << 2 + 2 << ends; // ( ends, not endl ) // ends is simply the // null character '\0' cout << a << endl; double v = 2; strcpy (a, "A sinus : "); b.seekp(strlen (a)); b << "sin (" << v << ") = " << sin(v) << ends; cout << a << endl; }
#include #include #include void main () { char a[1024]; istrstream b(a, 1024); strcpy (a, "45.656"); double k, p; b.seekg(0); // Start from first character. b >> k; k = k + 1; cout << k << endl; strcpy (a, "444.23 56.89"); b.seekg(0); b >> k >> p; cout << k << ", " << p + 1 << endl; }
#include #include void main () { int i; cout << "A list of numbers :" << endl; for (i = 1; i <= 1024; i *= 2) { cout.width (7); cout << i << endl; } cout << "A table of numbers :" << endl; for (i = 0; i <= 4; i++) { cout << setw(3) << i << setw(5) << i * i * i << endl; } }
In order to work correctly with C++ you will need a good reference book, just like you needed one for C.
You will also need information on how C++ is used in your particular domain of activity. The standards, the global approach, the tricks, the typical problems encountered and their solutions...