Lecture 2 :
C++ Features
Outline
• Scope Operator
• Namespaces
• Standard C++ header files
• Input/Output statements
• Bool type
• Constants
• Type casting
• Dynamic Memory Allocation
• Default Function Arguments
• Overloading of Function Names
• Call by value, Call by reference
1
C++ : As a Better C
C++ was developed from the C programming language,
by adding some extra features to it.
• Features which support OOP.
• Features which support generic programming
(templates).
2.3
Some Differences between C and C++
C C++
#include <stdio.h> #include <iostream>
int a; using namespace std;
printf(“Enter a number :"); int a;
scanf(“%d”, &a); cout << “Enter a number :";
printf(“%d \n”, a); cin >> a;
cout << a << endl;
int * p; int * p;
p = (int *) malloc ( sizeof (int) ); p = new int;
free(p); delete p;
struct Ornek { struct Ornek {
int a, b; int a, b;
} float ort_hesapla()
{ return (a+b) /2.0;}
}
#define TRUE 1 bool a;
#define FALSE 0 a = true;
int a;
a = TRUE;
2
Declarations and definitions
A declaration introduces a name (an identifier) to the
compiler. It does not allocate memory storage.
A definition tells the compiler to make a variable/function.
It allocates memory storage for the name.
In C, declarations and definitions must occur at the
beginning of a block.
In C++, declarations and definitions can be placed
anywhere prior to first used place.
2.5
Example: Declarations and definitions
Declarations Definitions
// Declaration of structure // Definition of a variable
struct ComplexT { int j;
float re, im;
}; // Definition of object variables
ComplexT c1, c2;
// Declaration of function prototype
// (its body is a definition)
void func( int, int);
2.6
3
Block Scope
A variable is available only in a block, in which it was defined.
The block is the scope of that variable.
Example :
int a=0;
for (int i=0; i < 100; i++)
{ // i is defined at the beginning of loop
a++;
int x=12; // Definition of local x variable
... // Scope of x is limited to loop
} // End of scope for i and x
cout << "i = " << i << endl;
Compiler errors
cout << "x = " << x << endl;
2.7
Scope Operator (::)
A definition in a block (local name) can hide a definition in an
enclosing (outer) block or a global name.
It is possible to use a global name by using the scope
operator ::
int x=1; // Global x
int y=0; // Global y
void f() { // Function is a new block
int x=5; // Local x=5, it hides global x
:: x ++; // Global x=2
x++; // Local x=6
y++; // Global y=1, scope operator is not necessary
}
Note: Give different names to global and local data.
2.8
4
Namespaces
A long program can be broken up into parts (in the same file or in different
files) maintained by different programmers.
In C, the programmers must be careful not to use the same names for
variables and functions in a project.
Standard C++ has a mechanism to prevent name collision:
The namespace keyword.
If some other definition has an identical name, but is in a different
namespace, then there is no collision.
If a variable or function does not belong to any namespace,
then it is defined in the global namespace.
2.9
Example: Namespaces
#include <iostream>
using namespace std;
namespace programmer1 { // programmer1's namespace
int flag; // programmer1's flag
void g(int); // programmer1's g function
} // end of namespace
namespace programmer2 { // programmer2's namespace
int flag; // programmer2's flag
}
int main() {
programmer1::flag = 3; // programmer1's flag
programmer2::flag = -5; // programmer2's flag
programmer1::g(6); // programmer1's g function
}
2.10
5
The using declaration
The using declaration statement makes it easier to access variables and
functions, which are defined in a namespace.
Example1: (Using only a selected item)
int main() {
using programmer1::flag;
// Applies to one item in the namespace
flag = 3; // programmer1::flag=3;
}
Example2: (Using all items)
int main() {
using namespace programmer1;
// Applies to all items in namespace
flag = 3; // programmer1::flag=3;
g(6); // programmer1's function g
}
2.11
Standard C++ header files
C++ eliminates the file extension for header files.
For example, instead of #include <iostream.h>
you can write: #include <iostream>
You can also use the header files by putting a “c” letter before the name.
#include <stdio.h> becomes #include <cstdio>
#include <stdlib.h> becomes #include <cstdlib>
The libraries that have been inherited from C are still available with the
traditional ‘.h’ extension.
2.12
6
The std Namespace
In standard C++ header files, all declarations and definitions take
place in a namespace called std.
The followings are common beginning statements in a C++ program:
#include <iostream>
using namespace std;
Some objects that the std namespace contains:
cin, cout, endl, string
2.13
Input / Output
Instead of C library functions (printf, scanf), in C++ the library
objects (cout, cin) are preferred to use for I/O operations.
When a C++ program includes the iostream header,
the following I/O stream objects are initialized:
• cin handles standard input (keyboard).
• cout handles standard output (screen).
2.14
7
The cout object
To print a value to the screen, write the word cout, followed by the
<< output operator.
If (using namespace std; ) statement is not written, then cout and
cin should be written with the (std::) prefix.
#include<iostream> // Header file for the cout object
int main() {
int i=5;
std::cout << "Integer number = " << i << endl;
}
2.15
The cin object
To read data from the keyboard, the predefined cin object is used with
the >> input operator.
If (using namespace std; ) statement is written,then the (std::) prefix is
not required for both cout and cin.
#include<iostream>
using namespace std;
// Below, cin and cout can be written without the (std::) prefix
int main() {
int i, j;
cout << "Give two numbers : ";
cin >> i >> j; // Read i and j from keyboard
cout << "Sum= " << i + j << "\n";
}
2.16
8
The type bool
The data type bool represents boolean (logical) values.
A logical value can be true or false.
The compiler considers nonzero values as true, zero values as false.
bool is_greater; // Boolean variable: is_greater
is_greater = false; // Assigning a logical value
int a=8, b=3;
………
is_greater = a > b; // Logical operation
if (is_greater) …… // Conditional operation
2.17
Constants
In C, directive #define is used to define constants.
#define PI 3.14
In C++, a named constant can be defined just like a variable, except
that its value cannot be changed.
const int MAX = 100; // MAX is constant.
MAX = 5; // Compiler Error! (MAX can not be changed)
The const word can be written before or after the type.
int const MAX = 100;
Uppercase letters are preferred for defining constants.
2.18
9
const pointers
The keyword const can be used in declaration of pointers.
There are three different cases:
a) The data pointed by the pointer is constant.
But the pointer itself may be changed.
const char *p = "ABC";
*p = 'Z'; // Compiler Error! Because data is constant.
p++; // Address in the pointer may change.
2.19
const pointers
b) The pointer itself is constant, which may not be changed.
Value pointed may be changed.
char * const sp = new char[5];
strcpy(sp, "ABC");
*sp = 'Z'; // data changed to "ZBC"
sp++; // Compiler Error! Because pointer is constant
c) Both the pointer and the pointed data are constants.
const char * const ssp = "ABC";
*ssp = 'Z'; // Compiler Error! Because data is constant
ssp++; // Compiler Error! Because pointer is const
2.20
10
Type Casts
C offers the following cast method to convert a data type to another type.
(typename) expression
Example: f = (float) i / 2; // i is integer and f is float
C++ offers the following cast methods.
All are template based operators (functions).
• static_cast
• const_cast
• reinterpret_cast
• dynamic_cast
(related to inheritance)
2.21
static_cast
The static_cast<type>(expression) operator is used to convert one type to
other type.
The < > syntax is used for template parameter.
int i=5;
float f;
// i is converted to float and divided by 2.
f = static_cast <float> (i) / 2;
Name of Template Function
operator parameter argument
(function)
2.22
11
const_cast
The const_cast<type>(expression) operator can be used for constant type
casting.
Example:
• p is a pointer to constant data.
• q is a pointer to non-constant data.
• The assignment q = p is not allowed.
const char *p = "ABC"; // p points to constant data
char *q; // data pointed by q may change
q = p; // Compiler Error! Constant data may change
q = const_cast <char *> (p);
*q = 'X'; // Compiler does not give error.
// But this command causes run-time error
2.23
reinterpret_cast
The reinterpret_cast<type>(expression) operator is used to reinterpret the
bytes in a variable.
Example: The individual bytes making up a structure can be reached using
a reinterpret_cast.
struct S { // Structure with 8 bytes
int i1, i2;
};
int main() {
S a; // a is of type S
a.i1 = 2000;
a.i2 = 3000;
unsigned char *p; // Pointer to unsigned chars (bytes)
p = reinterpret_cast <unsigned char *> (&a);
// Display the bytes of struct
for (int j=0; j<8; j++) // Count up to 8 bytes
cout << static_cast<int>(p[j]) << endl;
} // end of main
2.24
12
Dynamic Memory Allocation
In C, dynamic memory allocation is performed with standard library
functions malloc and free.
In C++ , the new and delete operators are used for dynamic memory
allocation.
int * ip; // A pointer to integer
ip = new int; // Memory allocation
……
delete ip; // Releasing the memory
An initialization value may also be provided.
int * ip; // ip is a pointer to integer
ip = new int(-50); // Memory allocation for one integer,
// initial value of integer is -50
2.25
Dynamic Memory Allocation
(array)
To define dynamic arrays, the new[size_of_array]
operator is used.
int * ipd;
ipd = new int[10]; // memory allocation for 10 integers
for (int k=0; k<10; k++)
ipd[k]= 2*k; // setting elements of the array
delete [] ipd; // releasing the whole array memory
2.26
13
Dynamic Memory Allocation
(struct)
The new and delete operators may also be used with
user defined data types such as a struct.
struct ComplexT { // A structure to define complex numbers
float re , im; // real and imaginary parts
};
ComplexT * cp = new ComplexT;
// cp is a pointer to ComplexT
……
delete cp; // releasing the memory
2.27
inline Functions
In C++, an inline function is defined using the same syntax as an ordinary
function.
Compiler makes a copy+paste of inline function codes, every time it is called.
Inline functions run faster.
Example:
#include <iostream>
using namespace std;
inline int MAX (int i1, int i2) {
if (i1 > i2) return i1;
else return i2;
}
int main() {
int a=5, b=8;
cout << MAX(a,b) << endl;
}
2.28
14
Default Function Arguments
Default values to parameters (arguments) can be written in a function.
In calling of the function, if the arguments are not given, default values are
used.
Example:
// i1 and i2 have default values
void f (char c, int i1=0, int i2=8)
{
cout << c << ' ' << i1 << ' ' << i2 << '\n';
…
}
The function may be called in three different ways:
f ('A', 4, 6); // c='A', i1=4, i2=6
f ('B', 3); // c='B', i1=3, i2=8
f ('C'); // c='C', i1=0, i2=8
f (); // Compiler error!
2.29
Default Function Arguments
When calling a function, arguments must be given from left to right:
f ('C', ,7); // ERROR! Third argument is given, but second is not.
While writing a function, default values of parameters must be written from
right to left without skipping any parameter.
void f (char c='A', int i1, int i2=8) {…}
// ERROR! i1 has been skipped
Valid void f (char c, int i1, int i2=8);
declarations: void f (char c, int i1=0, int i2=8);
void f (char c='A', int i1=0, int i2=8);
2.30
15
Overloading of function names
C++ enables several functions of the same name to be defined.
Functions should have different sets of parameters.
The name and the parameter list describe the signature (prototype) of
the function.
struct ComplexT { void print (float value) {
float re, im; // print function for float numbers
}; cout << "Value= " << value << endl;
}
int main() {
ComplexT z;
z.re=0.5; void print (ComplexT c) {
z.im=1.2; // print function for complex numbers
print(z); cout << "Real part = " << c.re
print(4.7); << "Imaginary part = " << c.im << endl;
} }
2.31
Reference Operator (&)
The reference operator (&) provides an alternative name for storage.
int i = 5;
int & j = i; // j is a reference to i.
// j and i both have the same memory address.
j is considered as an alias of i.
j++; // i = 6
2.32
16
Function Parameter Passing
In C, parameters are passed to functions always by their values
as the default mechanism (Call-by-Value).
To pass parameters by their addresses, pointers should be used.
If we want that the function can modify the original value of a
parameter, then we must send its address to the function.
There are two methods for this purpose:
• Call-by-Adress
• Call-by-Reference
(similar to call-by-adress)
2.33
Call by Value
Call by value
void calculate(int j)
{
j = (j * j) / 2; // j is local, so change will be locally only.
}
int main()
{
int i=6;
calculate(i); // i can not be modified.
cout << i;
} 6 Screen output
2.34
17
Call by Address
Call by address
void calculate(int * j) {
*j = (*j) * (*j) / 2;
// Modifies data which is pointed by j pointer.
// (*j in function body means the content of location pointed by j).
}
int main()
{
int i=6;
calculate(&i); // Address of i is sent, i can be modified by function.
cout << i;
} 18 Screen output
2.35
Call by Reference
Call by reference
void calculate(int & j) // j is a reference to the argument.
// Reference is same as an adress.
{
j = (j*j)/2; // j is used as a normal variable
}
int main( ) {
int i=6;
calculate(i); // A normal function call.
// Instead of value, address is sent.
// i can be modified.
cout << i;
Screen
} 18
output
2.36
18
Constant Reference
To prevent a function from changing a parameter, we should pass the
argument as constant reference.
struct Person { // A structure
char name [40]; // name : 40 bytes
int num; // number : 4 bytes
}; // Total of 44 bytes
void print (const Person & k) {
// k is a constant reference parameter
cout << "Name : " << k.name << endl;
cout << "Number : " << k.num << endl;
// k.num = 200; // Compiler error!
// Because k is constant.
}
Instead of 44 bytes
int main() {
(data),
Person x; // x is a variable of type Person
only 4 bytes
strcpy(x.name,"ABCD");
(reference of x) is
x.num=123; sent to the print()
print(x); // Function call function.
}
2.37
Return by Address
The function below returns a pointer to int, which is dynamically allocated.
int * f() { // Return type is pointer-to-int
int * x; // Pointer definition
x = new int; // Dynamic allocation of an integer
*x = 5; // Data is initialized
return x; // x is an adress
}
int main() {
int * p; // Pointer definition
p = f(); // Calling the function
cout << p << " : " << *p << endl;
// Displays the address and value (5)
} Screen output
0x280cf8 : 5
19