Lecture Week 10

advertisement
Object Oriented Programming COM326M1
Lecture 9-10
Pointers to Objects
We have seen how pointers can be used to access data. Since a class is also a data type,
a pointer can point to an object created by a class. The general form will be
Class_name *pointer;
Object pointers are useful in creating objects at run time. The pointers can then be used
to access the public members of an object. The general form is as follows:
pointer->memberFunction()
where memberFunction() is a method/function in the class.
Example 10.1
class item
{
int code;
float price;
public:
void getdata(int a, int b)
{ code=a;
price=b;
}
void show(void)
{
cout<<“Code:” << code<<”\n”;
<<”Price:” << price<<”\n”;
}
};
main()
{
item A;
item *Ptr=&A;
//object created
// ptr declared and initialised with address of A
Ptr->getdata(11, 2.99);
Ptr->show();
// This is same as
// A.getedata(11,2.99);
// A.show();
}
It is to be noted from this example that *ptr is an alias of object A.
Objects can also be created using pointers and new operator as follows
class_name *Ptr= new class_name
e.g. item *Ptr= new item;
This statement allocates enough memory space for the data members in the object
structure and assigns the address of the memory space to Ptr. Ptr can now be used to
refer to the members, e.g.
Ptr->show();
If the class has a constructor with parameters, then parameters should be provided when
creating the object.
An array of objects can also be created using pointers. The following example creates
an array of 10 objects of item.
item *Ptr= new item[10];
Example 10.2
class item
{
int code;
float price;
public:
void getdata(int a, int b)
{ code=a;
price=b;
}
void show(void)
{
cout<<“Code:” << code<<”\n”;
<<”Price:” << price<<”\n”;
}
};
const int size = 2;
main()
{
item *Ptr= new item[size];
item *d = Ptr;
int i,x;
float y;
for(i=0; i<size; i++)
{
cout<<”Input code and price for item” << i+1;
cin>>x>>y;
Ptr->getdata(x,y);
Ptr++;
}
for(i=0; i<size; i++)
{
cout<<”Item: ” << i+1 <<”\n”;
d->show();
d++;
}
}
this pointer
C++ uses a unique keyword called this to represent an object that invokes a member
function. ‘this’ is a pointer to object for which ‘this’ function was called. This unique
pointer is automatically passed to a member function when it is called. The pointer this
acts as an implicit parameter to all the member functions. If we have to reference the
object itself in a member function, we can do it through an implicit pointer this.
One important application of the pointer this is to return the object it points to, e.g.
return *this;
This statement assumes importance when we want to compare two or more objects
inside a member function and return the invoking object as a result, e.g.
person & person :: greater(person & x)
{
If (x.age>age)
return x
else
return *this;
}
Suppose we invoke this function by the call
C=A.greater(B);
The function will return the object B if the age of the person B is greater than that of A,
otherwise, it will return the object A using the pointer this.
Example 10.3
class person
{
char name[20];
float age;
public:
person (char *s, float a)
{
strcpy(name, s);
age=a;
}
person & person :: greater(person & x)
{
if(x.age>=age)
return x;
else
return *this;
}
void display(void)
{
cout<< “Name: “ << name << “\n”;
<< “Age: ” << age << “\n”;
}
};
main()
{
person P1("Paula", 37), P2("Abdul", 23), P3("Lutz", 40);
person P('\0', 0);
P=P1.greater(P3);
cout<<"The elder person is: \n";
P.display();
P=P1.greater(P2);
cout<<"The elder person is: \n";
P.display();
}
Virtual Functions
C++ virtual function is a member function of a class, whose functionality can be overridden in its derived classes. The whole function body can be replaced with a new set of
implementation in the derived class.
The difference between a non-virtual member function and a virtual member function is
that the non-virtual member functions are resolved at compile time. This mechanism is
called static binding. Where the virtual member functions are resolved during run-time.
This mechanism is known as dynamic binding. Virtual functions are accessed by using
object pointers. A virtual function in a base class must be defined even though it may
not be used.
Polymorphism
Polymorphism means the ability to take more than one form. For example, an operation
may exhibit different behaviour in different instances, which depends on type of data
used in the operation. Figure 1 shows that a single function name can be used to handle
different number and different types of arguments. This is shown in Example 10.4
above.
Window
Create()
Button: Object
Box: Object
Triangle: Object
Create(Button)
Create(box)
Create(triangle)
Figure 1: Polymorphism.
Example 10.4
This example assumes a base class named Window with a virtual member function
named Create. The derived class name will be Button, with over ridden function Create.
class Window // Base class for C++ virtual function example
{
public:
virtual void Create() // virtual function for virtual function example
{
cout <<"Base class Window"<<endl;
}
};
class Button : public Window
{
public:
void Create()
{
cout<<"Derived class Button - Overridden virtual function” <<endl;
}
};
void main()
{
Window *x, *y;
x = new Window();
x->Create();
y = new Button();
y->Create();
}
Template
Some times we find ourselves writing the same code over and over. The code is not
something that can be coded as function and called repeatedly. It requires different
classes and data types. Templates are new features of C++ that enable us to define
generic classes. We can define generic templates for both classes and member functions.
For example, a class template for an array would enable us to create arrays of various
types such as int array or float array. Similarly, we can define a template for a function,
say mul(), that can be used for creating various versions of mul() for multiplying int,
float and double types values.
Class Templates
The general form of a class template is
template <class T>
class Class_name
{
Class member specification
With anonymous type T
…….
};
Consider the example of a vector class defined as follows
Example 10.5
class vector
{
int *v;
int size;
public:
vector(int m) //create a null vector of size=m
{
v=new int[size=m];
for(int i=0; i<size; i++)
v[i]=0;
}
vector(int *a) //create a vector from an array
{
for(int i=0; i<size; i++)
v[i]=a[i];
}
int operator *(vector & y)
{
int sum=0;
for(int i=0; i<size; i++)
sum +=this->v[i]*y.v[i]
return sum;
}
};
main()
{
int x[3]={1,2,3};
int y[3]={4,5,6};
vector v1(3), v2(3);
v1=x;
v2=y;
int R=v1*v2;
cout<<”R=” << R;
}
Now suppose we need to define a vector of float type. To do this we need to redefine
the entire class. As mentioned earlier, it is simple process to create a generic class using
a template with an anonymous type, using a template class we can do this easily.
Example 10.6
Template <class T>
class vector
{
T *v;
int size;
public:
vector(int m) //create a null vector of size=m
{
v=new T[size=m];
for(int i=0; i<size; i++)
v[i]=0;
}
vector(T *a) //create a vector from an array
{
for(int i=0; i<size; i++)
v[i]=a[i];
}
T operator *(vector & y)
{
T sum=0;
for(int i=0; i<size; i++)
sum +=this->v[i]*y.v[i]
return sum;
}
};
main()
{
int x[4]={1,2,3,4};
float y[4]={4.1, 5.2, 6.3, 7.5};
vector <int> v1(4);
vector <float> v2(4);
v1=x;
v2=y;
float R=v1*v2;
cout<<”R=” << R;
}
Function Template
template <class T>
return_type Function_name
{
Body of function
With anonymous type T
…….
};
Example 10.7
template <class T>
void swap(T&x, T&y)
{
T temp;
temp=x;
x=y;
y=temp;
}
This essentially declares a set of overloaded function, one for each type of data. We can
invoke the function swap() like any ordinary function.
Example 10.8
void ff(int m, int n, float a, float b)
{
swap(m,n);
swap(a,b);
}
Download