| Goals for this chapter: |
|
This is the chapter about C++ programming language. C++ is the right
symbol to represent the extensions to the C language, as well a new level
of data abstraction and an object level. The C++ language was invented
by Dr. Bjarne Stroustrup
with the publication of different articles from 1983, introduce in C, the
concept of Class. The class facility is based on a similar facility available
in Simula 67.
C++ is different than C. C is a great programming language but C++ is better.
Without comparative adjectives, C++ is a powerful modern sucessor language to C.
In previous chapters we use the C Compiler or gcc (GNU C Compiler), in this chapter we need to move to c++ compiler.
[root@ftosx1 bin]# ls -al c++ g++
-rwxr-xr-x 4 root
root 80876 Jul 13 00:15 c++
-rwxr-xr-x 4 root
root 80876 Jul 13 00:15 g++
[root@ftosx1 bin]#
However, is not important to have a new extension, like "CC", "cpp", or "cxx"; the compiler will understand the source, also if we use the classical extension "c", for normal C source.
Therefore, we can have:
[root@ftosx1 The_C++_Programming_Language]# more hello_world.c
// The Hello world program.
// pg 46, sec 3.2, Hello, World!
// No guarantees offered. Constructive comments to bs@research.att.com
#include <iostream>
int main()
{
std::cout <<
"Hello, world!\n";
}
// note that "return 0;" isn't required in ISO C++
[root@ftosx1 The_C++_Programming_Language]# g++ hello_world.c
-o hello_world
[root@ftosx1 The_C++_Programming_Language]#
[root@ftosx1 The_C++_Programming_Language]# ./hello_world
Hello, world!
[root@ftosx1 The_C++_Programming_Language]#
Therefore is important to use the right compiler. The extension is superflous. The C++ inventor, Dr. Stroupstrup basically uses the "c" extension.
In C++ everything have a object-oriented perspective. For example in C++ is possible to "sum" strings.
Take for example the following example from Qt Manual.
Strings can be added to a list using append(), operator+=() or operator<<(), e.g.
QStringList fonts;
fonts.append( "Times" );
fonts += "Courier";
fonts += "Courier New";
fonts << "Helvetica [Cronyx]" <<
"Helvetica [Adobe]";
String lists have an iterator, QStringList::Iterator(), e.g.
for ( QStringList::Iterator it = fonts.begin();
it != fonts.end(); ++it ) {
cout << *it
<< ":";
}
cout << endl;
// Output:
// Times:Courier:Courier New:Helvetica
[Cronyx]:Helvetica [Adobe]:
Therefore, we can "add" strings, as numbers. The "magic" is not fact, the sucessfull is the abstract different data types (strings and numbers), and use them without to play attention to the role.
It is possible to extend a function to a new function using the parameters of the old function.
For example, a C++ declaration may be as follows:
const QMimeSource *m = QMimeSourceFactory::defaultFactory()->data( name );
Basically, we can create or re-use old objects with new ones;
C++ is available from 1985 (first edition of Bjarne Stroupstrup: The C++ Programming Language, now in its available is third edition, 1998), however important projects like GNOME are completely developed in C, instead of C++. This explain how C++ may be complex for a beginner, or basically may requery some level of abstraction and debugging that not necessarily is reached immediately.
However the sucessfull Qt and KDE projects are completely written in C++.
C++ is a new dimension ... a new planet in the mind. It is really interesting and beautifull from a esthetic designer point of view.
Are you ready ?
Before we start to code in C++ is important to know that from the
1983 until nowadays, the C++ changes and fix different standards. A major
upgrade happens from version 2 to version 3 (actual). Actual version, called
"version 3" is the ISO C++.
For example if we includes the .h we will get some minor errors because actually are not used anymore. These version are created by the C++ designer, Dr. Stroustrup.
Basically the "The C++ Programming Language - Third Edition" fix the new standard.
This is an example, about what happen if we includes includes files, with ".h".
[root@ftosx1 Chap6]# more example.cpp
#include <iostream.h>
#include <string.h>
using namespace std;
int main()
{
string s;
cout << "Please enter your first
name followed by a newline\n";
cin >> s;
cout << "Hello, " << s
<< '\n';
return 0; // this return statement
isn't necessary
}
[root@ftosx1 Chap6]#
[root@ftosx1 Chap6]# g++ example.cpp -o example
In file included from /usr/include/g++-v3/backward/iostream.h:31,
from example.cpp:1:
/usr/include/g++-v3/backward/backward_warning.h:32:2: warning:
#warning This file includes at least one deprecated or antiquated header.
Please consider using one of the 32 headers found in section 17.4.1.2 of
the C++ standard. Examples include substituting the <X> header for the
<X.h> header for C++ includes, or <sstream> instead of the deprecated
header <strstream.h>. To disable this warning use -Wno-deprecated.
[root@ftosx1 Chap6]#
The correct mode is as follows:
[root@ftosx1 Chap6]# more example.cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cout << "Please enter your first
name followed by a newline\n";
cin >> s;
cout << "Hello, " << s
<< '\n';
return 0; // this return statement
isn't necessary
}
[root@ftosx1 Chap6]#
The result is quite simple.
[root@ftosx1 Chap6]# g++ example.cpp -o example
[root@ftosx1 Chap6]# ./example
Please enter your first name followed by a newline
Giovanni A. Orlando
Hello, Giovanni
[root@ftosx1 Chap6]#
[root@ftosx1 Chap6]#
Note that we use the "namespace" std; that stand for standard. If we don't want to use this namespace (or convention) we need to add the word: "std" as a prefix on any used function.
For example, the previous code will works also as follows:
[root@ftosx1 Chap6]# more example2.cpp
#include <iostream>
#include <string>
//using namespace std;
int main()
{
std:: string s;
std::cout <<
"Please enter your first name followed by a newline\n";
std::cin >> s;
std::cout <<
"Hello, " << s << '\n';
return 0; // this return statement
isn't necessary
}
[root@ftosx1 Chap6]#
Compiling we will get the same result.
[root@ftosx1 Chap6]# ./example
Please enter your first name followed by a newline
Giovanni
Hello, Giovanni
[root@ftosx1 Chap6]#
Therefore using the "namespace" will save time and the code will be
more simple. However, we can also mix C includes with C++ includes. In
this case, is fundamental to avoid namespace and add the prefix representing
in full each declaration.
In C++, are present some new interesting operators from the
simple standard Input to get characters from the keyboard, or to print
variables, up to use functions as a member of class.
For example, in the previous example, suppose you want to print a program to transform dollars to euro .
In C++, we use the cout and cin operators for I/O.
Therefore as a preliminary program, we test I/O from the keyboard.
Our first example, will input a quantity in dollar and will print the output in euro.
[root@ftosx1 Chap6]# more dollar2euro.cpp
#include <iostream.h>
main ()
{
double mydollar;
cout << "\nInput dollar quantity:";
cin >> mydollar;
cout << "\nYou input\n" << mydollar << endl;
}
[root@ftosx1 Chap6]#
[root@ftosx1 Chap6]# c++ dollar2euro.cpp -o dollar2euro
[root@ftosx1 Chap6]# ./dollar2euro
Input dollar quantity:50
You input
50
[root@ftosx1 Chap6]#
cout is the C++ operator to print variables, while cin is the input operator.
The US$ - Euro rate changes at any moment. At the moment this chapter was developed, the rate is:
1 US Dollar = 0.99661 Euro
at http://www.oanda.com/convert/classic
Therefore, we update the source to do the math:
[root@ftosx1 Chap6]# more dollar2euro.cpp
#include <iostream>
using namespace std;
main ()
{
double mydollar;
cout << "\nInput dollar quantity:";
cin >> mydollar;
cout << mydollar << " US$ are " << mydollar*0.99661 << " euros" << endl;
}
[root@ftosx1 Chap6]#
Note here that this is extremely easy.
The class is the most used C++ concept
Suppose that in C you are working with a simple C structure books.
[root@ftosx1 Chap6]# more books1.c
/*****
* File: books.cpp
* Description: C motivation for classes
*
******/
typedef struct _book {
char title[30];
char author[30];
char editorial[30];
int book_id;
int publication_year;
} book;
void book_print(book *mylocalbook );
void insert_book (char *mytitle, char * myauthor, char * myeditorial,
int mybook_id, int mypublication_year );
void insert_book (char *mytitle, char * myauthor, char * myeditorial,
int mybook_id, int mypublication_year )
{
book mybook;
strcpy(mybook.title, mytitle);
strcpy(mybook.author, myauthor);
strcpy(mybook.editorial, myeditorial);
mybook.book_id = mybook_id;
mybook.publication_year = mypublication_year;
book_print( &mybook);
}
void book_print(book *mylocalbook )
{
printf ("%s %s %s %d %d\n", mylocalbook->title,
mylocalbook->author, mylocalbook->editorial,
mylocalbook->book_id, mylocalbook->publication_year);
}
main()
{
puts ("\nSome C and C++ books:\n");
insert_book ("C++ & C Tools", "David Spuler",
"Prentice Hall PTR", 20, 1988);
exit (0);
}
This example, works fine:
[root@ftosx1 Chap6]# make books1
cc books1.c
-o books1
[root@ftosx1 Chap6]# ./books1
Some C and C++ books:
C++ & C Tools David Spuler Prentice Hall PTR 20 1988
[root@ftosx1 Chap6]#
The Stroupstrup idea was to join the functions ... inside the structure and create the necessary enviroment to work!. This kind of geniality, generally changes things for ever.
Therefore now we motivate a class!
A valid C++ class may be as follows
class book {
private:
char title[30];
char author[30];
char editorial[30];
int book_id;
int publication_year;
public:
book(char * mytitle, char *myauthor, char * myeditorial,
int mybook_id, int mypublication_year );
void print();
};
Note that we includes the function inside the class. This is one of the C++ enhancements.
Now, when we write
s1 book s1("C++ & C Tools", "David Spuler", "Prentice Hall PTR", 91, 1996);
and
s1.print ();
We are calling a class component that is a function.
We also add and declare some members public and other private. This is a second C++ enhacements.
Now, we will create a C++ version with classes, based on the previous C example, based on structures.
We present here a numbered version and explain important points.
1 /*****
2 * File:
books.cpp
3 * Description: Introduce
classes and derived classes
4 *
5 ******/
6
7 #include <iostream>
8 #include <string>
9
10 using namespace std;
11
12 class book {
13 private:
14 char
title[30];
15 char
author[30];
16 char
editorial[30];
17 int
book_id;
18 int
publication_year;
19 public:
20 book(char * mytitle,
char *myauthor, char * myeditorial, int mybook_id, int mypublication_year
);
21 void print();
22 };
23
24 book::book(char *mytitle, char *
myauthor, char * myeditorial, int mybook_id, int mypublication_year )
25 {
26 strcpy(title,
mytitle);
27 strcpy(author,
myauthor);
28 strcpy(editorial,
myeditorial);
29
30 book_id = mybook_id;
31 publication_year
= mypublication_year;
32 }
33
34 void book::print()
35 {
36 cout <<
author << title << ", " << book_id << ", "
37
<< publication_year << "-" << editorial << endl;
38 }
39
40 main()
41 {
42 book
s1("C++ & C Tools", "David Spuler", "Prentice Hall PTR", 91, 1996);
43 book
s2("The C++ Programming Language", "Bjarne Stroustup", "Addison Wesley",
90, 1998);
44 book
s3("The C Programming Language", "Brian W. Kernigham and Dennis M. Ritchie",
"Prentice Hall PTR", 20, 1988);
45
46
47 cout <<
"\nSome C and C++ books:\n";
48
49 s1.print();
50 s2.print();
51 s3.print();
52 }
53
Here we define books like function with the same class. This choice is called constructor. Therefore a constructor is a member function whose name is the same as the class name.
In the previous example the constructor is: book
Declared inside the class
book(char * mytitle, char *myauthor, char * myeditorial, int mybook_id, int mypublication_year );
... and defined later
book::book(char *mytitle, char * myauthor, char * myeditorial,
int mybook_id, int mypublication_year )
{
strcpy(title, mytitle);
strcpy(author, myauthor);
strcpy(editorial, myeditorial);
book_id = mybook_id;
publication_year = mypublication_year;
}
book::print is a simple member of the class book.
To explain the previous source we can said the following:
[root@ftosx1 Chap6]# c++ books1.cpp -o
books1
[root@ftosx1 Chap6]# ./books1
Some C and C++ books:
David SpulerC++ & C Tools, 91, 1996-Prentice Hall PTR
Bjarne StroustupThe C++ Programming Language, 90, 1998-Addison
Wesley
Brian W. Kernigham and Dennis Prentice Hall PTRThe C Programming
Language, 20, 1988-Prentice Hall PTR
[root@ftosx1 Chap6]#
Now, we will explain some other examples about classes.
Another clear and elementary example about classes may be introduced working with complex numbers.
C++ offers these classes in the standard C++ Library.
Now, we will start with a simple example:
We suppose here that complex have a full implementation in C++, but this is not the case. Only a mininal implementation is provided, basically like "empty" objects where we can arrange our code.
[root@ftosx1 Chap6]# more complex.cpp
#include <complex>
#include <iostream>
using namespace std;
main ()
{
complex< float > ld = (5.0,8.23)
;
complex< double > lc1 = -3.0 ;
complex< double> lc = (5.1,8.23) ;
cout << ld << endl;
cout << lc << endl;
cout << "The real part of ld is " <<
ld.real() << endl;
cout << "The imaginary part of ld is
" << ld.imag() << endl;
cout << "The imaginary part of ld now is " << ld.imag() << endl;
}
[root@ftosx1 Chap6]#
Compiling and running we will have:
[root@ftosx1 Chap6]# g++ complex.cpp -o complex
[root@ftosx1 Chap6]# ./complex
(8.23,0)
(8.23,0)
The real part of ld is 8.23
The imaginary part of ld is 0
The imaginary part of ld now is 0
[root@ftosx1 Chap6]#
Note that neither the imaginary part is provided as a result.
A better implementation is made by the Dr. Stroupstroup:
[root@ftosx1 Chap6]# vi complex_out2.c
[root@ftosx1 Chap6]# more complex_out2.c
#include<iostream>
using namespace std;
// Note: my "complex"; not the one from the standard library
class complex {
public:
complex(double r
=0, double i =0) : re(r), im(i) { }
double real() const
{ return re; }
double imag() const
{ return im; }
// ...
private:
double re, im;
};
ostream& operator<<(ostream&s, const complex&
z)
{
return s <<
'(' << z.real() << ',' << z.imag() << ')';
}
int main()
{
complex x1(1,2);
complex x2(0.33,2.54);
cout << "x1
= " << x1 << '\n';
cout << "x2
= " << x2 << '\n';
return 0;
// redundant in ISO C++
}
[root@ftosx1 Chap6]#
[root@ftosx1 Chap6]# ./complex_out
x = (1,2)
[root@ftosx1 Chap6]#
Basically, we here had been re-written the "<<" operator for complex
numbers!
What we need to do if we want to get the "sum" of complex numbers, like we know from Mathematics ?
Easy, we need to overload the + operator.
/**********************************************************************
Filename: complex3.cpp
Chapter: 1 Overview of C++ and Object Oriented Programming
Compiler: Borland C++ Version 5.01 Summer 1998
C++ for C Programmers, Edition 3 By Ira Pohl
********************************************************************/
#include <iostream> //IO library
#include <string>
//string type
using namespace std;
//An elementary implementation of type complex
class complex {
public: //universal access to interface
//constructor
complex(double r=0, double im=0): real(r), imaginary(im) { }
//destructor
~complex() { cout << "destructor called on "; print(); }
void re_assign(double r) { real = r; }
void im_assign(double im) { imaginary = im; }
void print() const
{ cout << "(" << real << "," << imaginary << "i)" << endl; }
void print(string var_name) const
{ cout << var_name << " = "; print(); }
friend complex operator+(complex, complex);
private: //restricted access to implementation
double real, imaginary;
};
//overload +
complex operator+(complex x, complex y)
{
complex t;
t.real = x.real + y.real;
t.imaginary = x.imaginary + y.imaginary;
return t;
}
int main()
{
complex x(9.5, -4.5), y(4.2,6.0), z;
z = x + y;
x.print("x");
y.print("y");
z.print("z");
int look; cin >> look;
}
Here we will get our expectations:
[root@ftosx1 Chap6]# ./complex3
destructor called on (13.7,1.5i)
destructor called on (9.5,-4.5i)
destructor called on (4.2,6i)
x = (9.5,-4.5i)
y = (4.2,6i)
z = (13.7,1.5i)
Note that we here re-define the "+" operator.
This process is called "overloading" the operator. It is a basic technique in C++ programming. Originally the complex operator "+", is incomplete ... or expect to be overloaded for a full usage.
There are differet C++ compilers. We now list different:
class complex {
public: //universal access to interface
//constructor
complex(double r=0, double im=0): real(r), imaginary(im) { }
//destructor
~complex() { cout << "destructor called on "; print(); }
void re_assign(double r) { real = r; }
void im_assign(double im) { imaginary = im; }
void print() const
{ cout << "(" << real << "," << imaginary << "i)" << endl; }
void print(string var_name) const
{ cout << var_name << " = "; print(); }
friend complex operator+(complex, complex);
private: //restricted access to implementation
double real, imaginary;
};
If we comment the line: " //int look; cin >> look;"
we will get a new output including the destructor call
[root@ftosx1 Chap6]# ./complex3
destructor called on (13.7,1.5i)
destructor called on (9.5,-4.5i)
destructor called on (4.2,6i)
x = (9.5,-4.5i)
y = (4.2,6i)
z = (13.7,1.5i)
destructor called on (13.7,1.5i)
destructor called on (4.2,6i)
destructor called on (9.5,-4.5i)
[root@ftosx1 Chap6]#
Therefore, basically we are adding or allocating information when we add (or use the constructor) and this info will be free when we call the destructor.
Would our program works if we comment the destructor ? Why ?
The example we introduce before may be applied to any class.
For example, working with strings we will have:
[root@ftosx1 Chap6]# more string1.cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Please enter a
line:\n";
string s;
getline(cin,s);
cout << "You entered " << s << '\n';
}
[root@ftosx1 Chap6]# g++ string1.cpp -o string1
[root@ftosx1 Chap6]# ./string
Please enter a line:
FTLinuxCourse covers C++
You entered FTLinuxCourse covers C++
[root@ftosx1 Chap6]#
I prefer you investigate yourself on strings in C++.
Basically, it uses the "fstream" include to open/close/read streams.
We list now a
[root@ftosx1 Chap6]# more read_complex_numbers.cpp
/* Code for exercise 21.1.
|
| "C++ Solutions--Companion to The C++ Programming Language,
Third Edition"
| by David Vandevoorde; Addison-Wesley 1998; ISBN 0-201-30965-3.
|
| Permission to use, copy, modify, distribute and sell
this software
| and its documentation for any purpose is hereby granted
without fee.
| The author makes no representations about the suitability
of this
| software for any purpose. It is provided "as is"
without express or
| implied warranty.
`----------------------------------------------------------------------*/
#include <complex>
#include <fstream>
#include <iostream>
#include <stdlib.h>
void error(char const *prog, char const *entity,
char const *msg) {
std::cerr << prog << ": " <<
entity << msg << '\n';
exit(1);
}
int main(int argc, char *argv[]) {
if (argc!=2)
error(argv[0], "", ": unexpected
number of arguments.");
std::ifstream numbers(argv[1]);
if (!numbers)
error(argv[0], argv[1], ": cannot
open file for reading.");
double re, im;
while (numbers >> re) {
if (numbers >> im)
std::cout <<
std::complex<double>(re, im) << '\n';
else
std::cout <<
std::complex<double>(re, 0.0)
<< "\nWarning: odd number of values.\n";
}
return 0;
}
[root@ftosx1 Ch21]#
Compiling and reading we will get:
[root@ftosx1 Chap6]# g++ read_complex_numbers.cpp -o read_complex_numbers
[root@ftosx1 Chap6]# ./read_complex_numbers complex_numbers
(1,1.2)
(-1.1,-0.3)
(0.5,0.5)
(-0.1,0)
Warning: odd number of values.
[root@ftosx1 Chap6]#
Therefore, in C++ the process to open/read and close the file is made in the line:
std::ifstream numbers(argv[1]);
Similar process may be applied on files.
What does the "numbers" function ?
Please note that the previous example mix C and C++ include files.
One of the most innovative concept that C++ introduce is the "Derived
Classes" concept.
This means that a class may generate a new class, where the elements of the "father" class will be inherited by the new class.
An immediate and simple example, is the following:
Let be a class called student.
classs student {
public:
int student_id;
float grade;
char name[45];
char address[90];
enum {fresh, soph, junior, senior} year;
char major[10];
void print();
}
Then the "child" class; in C++ terms is called derived class will be:
classs graduate_student::public student {
public:
enum {ta, ra, fellowship, other} support;
char dept[15];
char thesis [100];
void print();
}
Any member of the first class will belong to the new class. This is the concept of derived (or inheritance).
So, the int student_id, grade, name, address, year, major and print() are inherited.
C++ uses the keywords: public, private and protected to access visibility to a specific member in the class.
A member function defined within the class definition (in other words, not simple declared there), is taken to be an inline member function.
So, using inline we may change a class as follows:
class Date {
public:
int day(), const
{return};
// ...
private:
int d, m, y;
}
Using inline we will simplify the previous class declaration.
class Date {
public:
int day() const;
// ...
private:
int d, m, y;
}
inline int Date::day() const {return d;}
In the same that in C we have our standard library, also C++ includes
its standard library.
Basically, the use of "namespace std" fix to apply the standard library includes and keywords, without others. Without this declaration, will be necessary to add the prefix: "std::XXX" to each variable.
The C++ library are
[root@ftosx1 Chap6]# ls -F /usr/include/g++-v3/
algorithm cctype clocale cstdarg
ctime exception
i386-ftosx-linux/ istream map
queue streambuf vector
backward/ cerrno cmath cstddef
cwchar exception_defines.h iomanip
iterator memory set
string
bits/ cfloat complex
cstdio cwctype ext/
ios
limits new sstream
typeinfo
bitset ciso646 csetjmp cstdlib
cxxabi.h fstream
iosfwd
list numeric stack
utility
cassert climits csignal cstring
deque functional
iostream locale
ostream stdexcept valarray
[root@ftosx1 Chap6]#
We complete this chapter with a simple example about strings:
[root@ftosx1 Chap6]# more string2.cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "Hello";
string s2 = "World";
string s3 =
s1 + "," + s2 + "\n";
cout << s3 ;
}
[root@ftosx1 Chap6]#
Compiling and running we will have:
[root@ftosx1 Chap6]# g++ string2.cpp -o string2
[root@ftosx1 Chap6]# ./string2
Hello,World
[root@ftosx1 Chap6]#
What is the C++ Library, as Linux library ?
| and | and_eq | asm | auto | bitand | bitor |
| bool | break | case | catch | char | class |
| compl | const | const_cast | continue | default | delete |
| do | double | dynamic_cast | else | enun | explicit |
| export | extern | false | float | for | friend |
| goto | if | inline | int | long | mutable |
| namespace | new | not | not_eq | operator | or |
| or_eq | private | protected | public | register | reinterpret_cast |
| return | short | signed | sizeof | static | static_cast |
| struct | switch | template | this | throw | true |
| try | typedef | typeid | typename | union | unsigned |
| using | virtual | void | volatile | wchar_t | while |
| xor | xor_eq |
Do you like C++?
C++ is really a great language and a valid C extension. Working with classes and in a Object-Oriented Programming (OOP) is more interesting that on the classic C.
The book "The C++ Programming Language" - 3rd edition written by Bjarne Stroustrup, includes 911 pages. However, in this chapter we resume the most important concepts to get started and start to code. The most significative elements in C++ programming are covered.
Basically, no other reading is necessary. Both the code for this books and its companion: "The C++ Solution" by David Vandevoorde offers a sufficient material for a preliminary further reading.
A latest source is "C for C++ Programmers" by Ira Pohl (Only strange names between C++ authors).
Will be the daily KDE, Qt or C++ code to complete the C++ education.
Consult the answers
Check the Interactive Exam Cram Programming:
Internet Resources for this Chapter.