Object Oriented Programming Using C++
Functions
Functions allow to structure programs in segments of code to perform individual tasks.
In C++, a function is a group of statements that is given a name, and which can be called from some point of the program. The most common syntax to define a function is:
type name ( parameter1, parameter2, ...) { statements }
Where:
- type is the type of the value returned by the function.
- name is the identifier by which the function can be called.
- parameters (as many as needed): Each parameter consists of a type followed by an identifier, with each parameter being separated from the next by a comma. Each parameter looks very much like a regular variable declaration (for example:int x), and in fact acts within the function as a regular variable which is local to the function. The purpose of parameters is to allow passing arguments to the function from the location where it is called from.
- statements is the function's body. It is a block of statements surrounded by braces { } that specify what the function actually does.
Let's have a look at an example:
// function example
#include <iostream>
using namespace std;
int addition (int a, int b)
{
int r;
r=a+b;
return r;
}
int main ()
{
int z;
z = addition (5,3);
cout << "The result is " << z;
}
A function can actually be called multiple times within a program, and its argument is naturally not limited just to literals:
#include <iostream>
using namespace std;
// function declaration
int max(int num1, int num2);
int main ()
{
// local variable declaration:
int a = 100;
int b = 200;
int ret;
// calling a function to get max value.
ret = max(a, b);
cout << "Max value is : " << ret << endl;
return 0;
}
// function returning the max between two numbers
int max(int num1, int num2)
{
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
#include <iostream>
using namespace std;
int sum(int a, int b=20)
{
int result;
result = a + b;
return (result);
}
int main ()
{
// local variable declaration:
int a = 100;
int b = 200;
int result;
// calling a function to add the values.
result = sum(a, b);
cout << "Total value is :" << result << endl;
// calling a function again as follows.
result = sum(a);
cout << "Total value is :" << result << endl;
return 0;
}
//Random Numbers
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main ()
{
int i,j;
// set the seed
srand( (unsigned)time( NULL ) );
/* generate 10 random numbers. */
for( i = 0; i < 10; i++ )
{
// generate actual random number
j= rand();
cout <<" Random Number : " << j << endl;
}
return 0;
}
// function example
#include <iostream>
using namespace std;
int subtraction (int a, int b)
{
int r;
r=a-b;
return r;
}
int main ()
{
int x=5, y=3, z;
z = subtraction (7,2);
cout << "The first result is " << z << '\n';
cout << "The second result is " << subtraction (7,2) << '\n';
cout << "The third result is " << subtraction (x,y) << '\n';
z= 4 + subtraction (x,y);
cout << "The fourth result is " << z << '\n';
}
The first result is 5
The second result is 5
The third result is 2
The fourth result is 6
Let's examine each of these calls, bearing in mind that each function call is itself an expression that is evaluated as the value it returns. Again, you can think of it as if the function call was itself replaced by the returned value:
1
2 z = subtraction (7,2);
cout << "The first result is " << z;
If we replace the function call by the value it returns (i.e., 5), we would have:
1
2 z = 5;
cout << "The first result is " << z;
With the same procedure, we could interpret:
cout << "The second result is " << subtraction (7,2);
as:
cout << "The second result is " << 5;
since 5 is the value returned by subtraction (7,2).
In the case of:
cout << "The third result is " << subtraction (x,y);
// void function example
#include <iostream>
using namespace std;
void printmessage ()
{
cout << "I'm a function!";
}
int main ()
{
printmessage ();
}
// passing parameters by reference
#include <iostream>
using namespace std;
void duplicate (int& a, int& b, int& c)
{
a*=2;
b*=2;
c*=2;
}
int main ()
{
int x=1, y=3, z=7;
duplicate (x, y, z);
cout << "x=" << x << ", y=" << y << ", z=" << z;
return 0;
}
x=2, y=6, z=14
// default values in functions
#include <iostream>
using namespace std;
int divide (int a, int b=2)
{
int r;
r=a/b;
return (r);
}
int main ()
{
cout << divide (12) << '\n';
cout << divide (20,4) << '\n';
return 0;
}
// declaring functions prototypes
#include <iostream>
using namespace std;
void odd (int x);
void even (int x);
int main()
{
int i;
do {
cout << "Please, enter number (0 to exit): ";
cin >> i;
odd (i);
} while (i!=0);
return 0;
}
void odd (int x)
{
if ((x%2)!=0) cout << "It is odd.\n";
else even (x);
}
void even (int x)
{
if ((x%2)==0) cout << "It is even.\n";
else odd (x);
}
// factorial calculator
#include <iostream>
using namespace std;
long factorial (long a)
{
if (a > 1)
return (a * factorial (a-1));
else
return 1;
}
int main ()
{
long number = 9;
cout << number << "! = " << factorial (number);
return 0;
}
Overloaded functions
In C++, two different functions can have the same name if their parameters are different; either because they have a different number of parameters, or because any of their parameters are of a different type. For example:
// overloading functions
#include <iostream>
using namespace std;
int operate (int a, int b)
{
return (a*b);
}
double operate (double a, double b)
{
return (a/b);
}
int main ()
{
int x=5,y=2;
double n=5.0,m=2.0;
cout << operate (x,y) << '\n';
cout << operate (n,m) << '\n';
return 0;
}
Function templates
Overloaded functions may have the same definition. For example:
// overloaded functions
#include <iostream>
using namespace std;
int sum (int a, int b)
{
return a+b;
}
double sum (double a, double b)
{
return a+b;
}
int main ()
{
cout << sum (10,20) << '\n';
cout << sum (1.0,1.5) << '\n';
return 0;
}
// function template
#include <iostream>
using namespace std;
template <class T>
T sum (T a, T b)
{
T result;
result = a + b;
return result;
}
int main () {
int i=5, j=6, k;
double f=2.0, g=0.5, h;
k=sum<int>(i,j);
h=sum<double>(f,g);
cout << k << '\n';
cout << h << '\n';
return 0;
}
// function templates
#include <iostream>
using namespace std;
template <class T, class U>
bool are_equal (T a, U b)
{
return (a==b);
}
int main ()
{
if (are_equal(10,10.0))
cout << "x and y are equal\n";
else
cout << "x and y are not equal\n";
return 0;
}
Non-type template arguments
The template parameters can not only include types introduced by class or typename, but can also include expressions of a particular type
// template arguments
#include <iostream>
using namespace std;
template <class T, int N>
T fixed_multiply (T val)
{
return val * N;
}
int main() {
std::cout << fixed_multiply<int,2>(10) << '\n';
std::cout << fixed_multiply<int,3>(10) << '\n';
}
Example to Explain Working of Object and Class in C++ Programming
/* Program to illustrate working of Objects and Class in C++ Programming */
#include <iostream>
using namespace std;
class temp
{
private:
int data1;
float data2;
public:
void int_data(int d){
data1=d;
cout<<"Number: "<<data1;
}
float float_data(){
cout<<"\nEnter data: ";
cin>>data2;
return data2;
}
};
int main(){
temp obj1, obj2;
obj1.int_data(12);
cout<<"You entered "<<obj2.float_data();
return 0;
}
Classes (I)
Classes are an expanded concept of data structures: like data structures, they can contain data members, but they can also contain functions as members.
An object is an instantiation of a class. In terms of variables, a class would be the type, and an object would be the variable.
Classes are defined using either keyword class or keyword struct, with the following syntax:
class class_name {
access_specifier_1:
member1;
access_specifier_2:
member2;
...
} object_names;
Here is the complete example of class Rectangle:
// classes example
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
void set_values (int,int);
int area() {return width*height;}
};
void Rectangle::set_values (int x, int y) {
width = x;
height = y;
}
int main () {
Rectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
return 0;
}
// classes example
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
void set_values (int,int);
int area() {return width*height;}
};
void Rectangle::set_values (int x, int y) {
width = x;
height = y;
}
int main () {
Rectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
return 0;
}
Constructors
What would happen in the previous example if we called the member function area before having called set_values? An undetermined result, since the members width and height had never been assigned a value.
In order to avoid that, a class can include a special function called its constructor, which is automatically called whenever a new object of this class is created, allowing the class to initialize member variables or allocate storage.
This constructor function is declared just like a regular member function, but with a name that matches the class name and without any return type; not even void.
The Rectangle class above can easily be improved by implementing a constructor:
// example: class constructor
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
Rectangle (int,int);
int area () {return (width*height);}
};
Rectangle::Rectangle (int a, int b) {
width = a;
height = b;
}
int main () {
Rectangle rect (3,4);
Rectangle rectb (5,6);
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
return 0;
}
Overloading constructors
Like any other function, a constructor can also be overloaded with different versions taking different parameters: with a different number of parameters and/or parameters of different types. The compiler will automatically call the one whose parameters match the arguments:
// overloading class constructors
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
Rectangle ();
Rectangle (int,int);
int area (void) {return (width*height);}
};
Rectangle::Rectangle () {
width = 5;
height = 5;
}
Rectangle::Rectangle (int a, int b) {
width = a;
height = b;
}
int main () {
Rectangle rect (3,4);
Rectangle rectb;
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
return 0;
}
Friend functions
In principle, private and protected members of a class cannot be accessed from outside the same class in which they are declared. However, this rule does not apply to "friends".
Friends are functions or classes declared with the friend keyword.
A non-member function can access the private and protected members of a class if it is declared a friend of that class. That is done by including a declaration of this external function within the class, and preceding it with the keyword friend:
// friend functions
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
Rectangle() {}
Rectangle (int x, int y) : width(x), height(y) {}
int area() {return width * height;}
friend Rectangle duplicate (const Rectangle&);
};
Rectangle duplicate (const Rectangle& param)
{
Rectangle res;
res.width = param.width*2;
res.height = param.height*2;
return res;
}
int main () {
Rectangle foo;
Rectangle bar (2,3);
foo = duplicate (bar);
cout << foo.area() << '\n';
return 0;
}
Friend classes
Similar to friend functions, a friend class is a class whose members have access to the private or protected members of another class:
// friend class
#include <iostream>
using namespace std;
class Square;
class Rectangle {
int width, height;
public:
int area ()
{return (width * height);}
void convert (Square a);
};
class Square {
friend class Rectangle;
private:
int side;
public:
Square (int a) : side(a) {}
};
void Rectangle::convert (Square a) {
width = a.side;
height = a.side;
}
int main () {
Rectangle rect;
Square sqr (4);
rect.convert(sqr);
cout << rect.area();
return 0;
}
Inheritance between classes
Classes in C++ can be extended, creating new classes which retain characteristics of the base class. This process, known as inheritance, involves a base class and a derived class: The derived class inherits the members of the base class, on top of which it can add its own members.
For example, let's imagine a series of classes to describe two kinds of polygons: rectangles and triangles. These two polygons have certain common properties, such as the values needed to calculate their areas: they both can be described simply with a height and a width (or base).
This could be represented in the world of classes with a class Polygon from which we would derive the two other ones:Rectangle and Triangle:
The inheritance relationship of two classes is declared in the derived class. Derived classes definitions use the following syntax:
class derived_class_name: public base_class_name
{ /*...*/ };
// derived classes
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b;}
};
class Rectangle: public Polygon {
public:
int area ()
{ return width * height; }
};
class Triangle: public Polygon {
public:
int area ()
{ return width * height / 2; }
};
int main () {
Rectangle rect;
Triangle trgl;
rect.set_values (4,5);
trgl.set_values (4,5);
cout << rect.area() << '\n';
cout << trgl.area() << '\n';
return 0;
}
What is inherited from the base class?
In principle, a publicly derived class inherits access to every member of a base class except:
• its constructors and its destructor
• its assignment operator members (operator=)
• its friends
• its private members
Even though access to the constructors and destructor of the base class is not inherited as such, they are automatically called by the constructors and destructor of the derived class.
Unless otherwise specified, the constructors of a derived class calls the default constructor of its base classes (i.e., the constructor taking no arguments). Calling a different constructor of a base class is possible, using the same syntax used to initialize member variables in the initialization list:
derived_constructor_name (parameters) : base_constructor_name (parameters) {...}
For example:
// constructors and derived classes
#include <iostream>
using namespace std;
class Mother {
public:
Mother ()
{ cout << "Mother: no parameters\n"; }
Mother (int a)
{ cout << "Mother: int parameter\n"; }
};
class Daughter : public Mother {
public:
Daughter (int a)
{ cout << "Daughter: int parameter\n\n"; }
};
class Son : public Mother {
public:
Son (int a) : Mother (a)
{ cout << "Son: int parameter\n\n"; }
};
int main () {
Daughter kelly(0);
Son bud(0);
return 0;
}
Multiple inheritance
A class may inherit from more than one class by simply specifying more base classes, separated by commas, in the list of a class's base classes (i.e., after the colon). For example, if the program had a specific class to print on screen calledOutput, and we wanted our classes Rectangle and Triangle to also inherit its members in addition to those of Polygon we could write:
1
2 class Rectangle: public Polygon, public Output;
class Triangle: public Polygon, public Output;
Here is the complete example:
// multiple inheritance
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
Polygon (int a, int b) : width(a), height(b) {}
};
class Output {
public:
static void print (int i);
};
void Output::print (int i) {
cout << i << '\n';
}
class Rectangle: public Polygon, public Output {
public:
Rectangle (int a, int b) : Polygon(a,b) {}
int area ()
{ return width*height; }
};
class Triangle: public Polygon, public Output {
public:
Triangle (int a, int b) : Polygon(a,b) {}
int area ()
{ return width*height/2; }
};
int main () {
Rectangle rect (4,5);
Triangle trgl (4,5);
rect.print (rect.area());
Triangle::print (trgl.area());
return 0;
}
Polymorphism
Before getting any deeper into this chapter, you should have a proper understanding of pointers and class inheritance. If you are not really sure of the meaning of any of the following expressions, you should review the indicated sections:
Statement: Explained in:
int A::b(int c) { } Classes
a->b Data structures
class A: public B {}; Friendship and inheritance
Pointers to base class
One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.
The example about the rectangle and triangle classes can be rewritten using pointers taking this feature into account:
// pointers to base class
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
};
class Rectangle: public Polygon {
public:
int area()
{ return width*height; }
};
class Triangle: public Polygon {
public:
int area()
{ return width*height/2; }
};
int main () {
Rectangle rect;
Triangle trgl;
Polygon * ppoly1 = ▭
Polygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << rect.area() << '\n';
cout << trgl.area() << '\n';
return 0;
}
Abstract base classes
Abstract base classes are something very similar to the Polygon class in the previous example. They are classes that can only be used as base classes, and thus are allowed to have virtual member functions without definition (known as pure virtual functions). The syntax is to replace their definition by =0 (an equal sign and a zero):
An abstract base Polygon class could look like this:
1
2
3
4
5
6
7
8
9 // abstract class CPolygon
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area () =0;
};
// abstract base class
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
};
class Rectangle: public Polygon {
public:
int area (void)
{ return (width * height); }
};
class Triangle: public Polygon {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
Rectangle rect;
Triangle trgl;
Polygon * ppoly1 = ▭
Polygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << ppoly1->area() << '\n';
cout << ppoly2->area() << '\n';
return 0;
}
Here is an example that combines some of the features in the latest chapters, such as dynamic memory, constructor initializers and polymorphism:
// dynamic allocation and polymorphism
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
Polygon (int a, int b) : width(a), height(b) {}
virtual int area (void) =0;
void printarea()
{ cout << this->area() << '\n'; }
};
class Rectangle: public Polygon {
public:
Rectangle(int a,int b) : Polygon(a,b) {}
int area()
{ return width*height; }
};
class Triangle: public Polygon {
public:
Triangle(int a,int b) : Polygon(a,b) {}
int area()
{ return width*height/2; }
};
int main () {
Polygon * ppoly1 = new Rectangle (4,5);
Polygon * ppoly2 = new Triangle (4,5);
ppoly1->printarea();
ppoly2->printarea();
delete ppoly1;
delete ppoly2;
return 0;
}
تعليقات
إرسال تعليق
شاركنا الآراء ،،