0% found this document useful (0 votes)
63 views

Lecture 3 - A Closer Look at Classes

The document discusses passing objects as parameters to functions and returning objects from functions in C++. Passing objects by value can cause problems if the objects allocate dynamic memory. It's better to pass the address of the object. When returning objects from functions, a temporary copy is made and destroyed after the call, which could cause issues.

Uploaded by

emon
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views

Lecture 3 - A Closer Look at Classes

The document discusses passing objects as parameters to functions and returning objects from functions in C++. Passing objects by value can cause problems if the objects allocate dynamic memory. It's better to pass the address of the object. When returning objects from functions, a temporary copy is made and destroyed after the call, which could cause issues.

Uploaded by

emon
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

8/17/2014

Lecture Three

A Closer Look at Classes

Ref: Herbert Schildt, Teach Yourself C++, Third Edn (Chapter 2)

© Dr. M. Mahfuzul Islam


Professor, Dept. of CSE, BUET

Assigning Objects
One object can be assigned to another provided that both objects are
of the same type.
When one object is assigned to another, a bitwise copy of all the data
members is made.

#include <iostream> int main() {


using namespace std; myclass o1, o2;

class myclass { o1.set(10, 4);


int a, b; o2 = o1;
public: o1.show();
void set(int i, int j) { a = i; b = j;} 02.show();
void show() { cout << a << ‘ ‘ << return 0;
b << ‘\n’; } }
};

1
8/17/2014

Assigning Objects
#include <iostream> char stack::pop(){
using namespace std; if (tos == 0){
cout << “Stack is empty\n”;
#define SIZE 10 return;
}
class stack { return stck[--tos];
char stck[SIZE]; }
int tos;
public: int main(){
stack() {tos = 0}; stack s1, s2;
void push(char ch);
char pop(); s1.push(‘a’);
}; s1.push(‘b’);

void stack::push(char ch){ s2 = s1;


if (tos == SIZE){ cout << s1.pop() << ‘ ‘ << s1.pop()<<“\n”;
cout << “Stack is full\n”; cout << s2.pop() << ‘ ‘ << s2.pop()<<“\n”;
return; return 0;
} }
stck[tos++] = ch;
}

The outputs are identical.

Assigning Objects: Error Possibility


Must exercise some care when assigning one object to another
#include <iostream> strtype::~strtype(){
#include <cstring> cout << “freeing p…….\n”;
#include <cstdlib> free(p);
using namespace std; }
class strtype { void strtype::show(){
char *p; cout << p << “ – length: “ << len;
int len; cout << ‘\n’;
public: }
strtype(char *ptr);
int main(){
~strtype();
strtype s1(“This is a test.”), s2(“I like C++”);
void show();
};
s1.show();
strtype::strtype(char *ptr){ s2.show();
len = strlen(ptr);
p = (char *) malloc(len+1); s2 = s1;
if (!p) { s1.show();
When the objects are
cout << “Allocation error\n”; s2.show(); destroyed, the memory
exit(1); return 0; pointed to by s1’s p is
} } freed twice and the
strcpy(p, ptr); memory pointed to by
} s2’s p is not freed at all.
What is the problem?

2
8/17/2014

Passing Objects to Functions


Parameter passing, by default, is called by value.
New object does not call constructor, but destructor is called

#include <iostream> void sqr_it(samp o) {


using namespace std; o.set_i(o.get_i() * o.get_i());
class samp { cout << “Copy: value of a:” << o.get_i() << ‘\n’;
int i; }
public:
samp(int n); int main() {
~samp(); samp a(10);
void set_i(int n) {i= n;}
int get_i() { return i} sqr_it(a);
}; cout << “Main: value of a:” << a.get_i() << ‘\n’;
return 0;
samp::samp(int n){ }
i = n;
count << “Constructing…\n”;
}
OUTPUT:
samp::~samp(){ Constructing….
count << “Destructing…\n”; Copy: value of a: 100
} Destructing….
Main: value of a: 10
Destructing….

Passing Objects to Functions: Problem


If the object used as the arguments allocates dynamic memory and free the
memory then the destructor function is called and the original object is damaged.
#include <iostream> void neg (dyna ob) {
#include <cstdlib> return -ob.get();
using namespace std; }
class dyna {
int main() {
int *p;
dyna o(-10);
public:
dyna(int i);
cout << o.get() << ‘\n’;
~dyna() {free(p); cout << “Freeing…\n”;}
cout << neg(o) << ‘\n’;
int get () { return *p}
cout << o.get() << ‘\n’;
};
return 0;
dyna::dyna(int i){ }
p = (int *) malloc( sizeof(int) );
if (!p) {
OUTPUT:
cout << “Allocation problem\n”;
-10
exit(1);
Freeing… // when o is passed to neg(), copy is
}
//created and destroyed in neg()
*p = i;
10
}
NULL pointer assignment // o.get()
NULL pointer assignment // free(p) in destructor
Freeing…..//when o is destroyed

3
8/17/2014

Passing Objects to Functions: Solutions


Solutions:
To pass the address of the object, not the object itself.
A special type of constructor called “copy constructor” is used (Chap 5).

#include <iostream> void sqr_it(samp *o) {


using namespace std; o.set_i(o.get_i() * o.get_i());
class samp { cout << “Copy: value of i:” << o.get_i() << ‘\n’;
int i; }
public:
samp(int n) { i = n;} int main() {
void set_i(int n) {i= n;} samp a(10);
int get_i() { return i}
}; sqr_it(&a);
cout << “Main: value of i:” << a.get_i() << ‘\n’;
samp::~samp(){ return 0;
count << “Destructing…\n”; }
}

OUTPUT:
copy: value of i: 100
main: value of i: 100

Returning Objects from Functions


When an object is returned by a function, a temporary object is created which
holds the return value. This object is return by the function.
After the value has been returned, this object is destroyed.
The destruction of this temporary object may cause unexpected side effects.
#include <iostream> samp input() {
#include <cstring> char s[80];
#include <cstdlib> samp str;
using namespace std;
cout <<”Enter a string: ”;
class samp {
cin >> s;
char *s;
str.set(s);
public:
return str;
samp() { s = ‘\0’; }
}
~samp() { if (s) free(s); count << “Freeing
S\n”;}
void show() {cout << s << ’\n’;}
int main() {
void set (char *str);
samp ob;
};

void samp::set(char *str){ ob = input();


s = (char *) malloc(strlen(str)+1); ob.show();
if(!s) { cout << “Allocation error\n”; return 0;
exit(1);} }
strcpy(s, str);
}

4
8/17/2014

Friend Function

A friend function is not a member of a class but still has


access to its private elements.
Three uses of friend functions
(1) to do operator overloading;
(2) creation of certain types of I/O functions; and
(3) one function to have access to the private members of two or more
different classes.
A friend function is a regular non-member function

Friend Function

#include <iostream> int main() {


using namespace std; int t;
class truck; car c(6, 55);
truck t(2000, 72);
class car {
int passengers; t = sp_greater(c, t);
int speed; if (t > 0) cout << ”Faster.\n”;
public: else if (t==0) cout << “Equal.\n”;
car(int p, int s) { passengers = p; speed = s; } else count << “slower.\n”;
friend int sp_greater(car c, truck t);
}; return 0;
}
class truck {
int weight;
int speed;
public:
car(int w, int s) { weight = w; speed = s; } Forward declaration:
friend int sp_greater(car c, truck t);
}; class truck;
int sp_greater (car c, truck t) {
return c.speed – t.speed;
}

5
8/17/2014

Friend Function

A friend function can be a member of one class and a friend of another.


#include <iostream> int car::sp_greater (truck t) {
using namespace std; return speed – t.speed;
}
class truck;
int main() {
class car { int t;
int passengers; car c(6, 55);
int speed; truck t(2000, 72);
public:
car(int p, int s) { passengers = p; speed = s; } t = c. sp_greater(t);
int sp_greater(truck t); if (t > 0) cout << ”Faster.\n”;
}; else if (t==0) cout << “Equal.\n”;
else count << “slower.\n”;
class truck {
int weight; return 0;
int speed; }
public:
car(int w, int s) { weight = w; speed = s; } t = c.sp_greater(t);
friend int car::sp_greater(truck t); can be written by the scope resolution
}; operator (::) as
t =c.car::sp_greater(t);
but this is unnecessary.

You might also like