C++ Programming Tutorial II
Classes and Objects
|
Classes
class class-name {
private data and functions
access-specifier:
data and functions
access-specifier:
data and functions
...
...
...
access-specifier:
data and functions
} object-list;
|
class employee {
char name[80];
double wage;
public:
void putname (char *n);
void getname (char *n);
void putwage (double w);
double getwage();
};
|
- A class is a logical abstraction, but an object has physical existence.
- access-specifier can be:
- public:
Allow functions or data to be accessible to other parts of the program.
- private:
May be accessed only by other members of the class.
- protected:
Used when inheritance is involved; discussed later.
Friend Functions
#include <iostream.h>
class myclass {
int a, b;
public:
friend int sum(myclass x);
void set_ab(int i, int j);
};
void myclass::set_ab (int i, int j)
{
a = i;
b = j;
}
// Note: sum() is not a member function of any class.
int sum (myclass x)
{
/* Because sum() is a friend of myclass, it can
directly access a and b. */
return x.a + x.b;
}
|
main()
{
myclass n;
n.set_ab (3, 4);
cout << sum(n);
return 0;
}
|
- A friend function has access to all private and
protected (and public of course) members of the class for
which it is a friend.
#include <iostream.h>
#define IDLE 0
#define INUSE 1
class C2; // forward declaration
class C1 {
int status; // IDLE if off; INUSE if on screen
public:
void set_status(int state);
friend int idle(C1 a, C2 b);
};
class C2 {
int status; // IDLE if off; INUSE if on screen
public:
void set_status(int state);
friend int idle(C1 a, C2 b);
};
void C1::set_status (int state)
{
status = state;
}
void C2::set_status (int state)
{
status = state;
}
int idle (C1 a, C2 b)
{
if (a.status || b.status)
return 0;
else
return 1;
}
|
main()
{
C1 x;
C2 y;
x.set_status(IDLE);
y.set_status(IDLE);
if (idle(x, y))
cout << "Screen can be used.\n";
else
cout << "In use.\n";
x.set_status(INUSE);
if (idle(x, y))
cout << "Screen can be used.\n";
else
cout << "In use.\n";
return 0;
}
|
- Two or more classes may contain members that are interrelated relative to
other parts of a program.
- One function (idle()) is called, instead of two
(C1::get_status() and C2::get_status()), thus more
efficient.
Friend Classes
#include <iostream.h>
class coins {
// The following is a private enumeration
enum units {penny, nickel, dime, quarter, half_dollar};
friend class amount;
}
class amount {
coins::units money; // notice use of coins::units
public:
void setm();
int getm();
} ob;
void amount::setm()
{
// Enumeration units accessible here because
// amout is friend of coins.
money = coins::dime;
}
int amount::getm()
{
return money;
}
main()
{
ob.setm();
cout << ob.getm(); // outputs the number 2
return 0;
}
- A friend class has access to the private names defined within the other
class.
- When one class is a friend of another, it only has access to names defined
within the other class, i.e. it does not inherit the other class.
Inline Functions
#include <iostream.h>
inline int max(int a , int b)
{
return a>b ? a : b;
}
main()
{
cout << max(10, 20);
cout << " " << max(99, 88);
return 0;
}
#include <iostream.h>
main()
{
cout << (10 > 20 ? 10 : 20);
cout << " " << (99 > 88 ? 99 : 88);
return 0;
}
- Inline functions are short functions that are not actually called; rather,
their code is expanded inline at the point of each invocation.
- Although expanding function calls inline can produce faster run times, it
also often results in larger code size because of the duplicated code.
- The compiler can choose to ignore the inline specification.
#include <iostream.h>
class myclass {
int a, b;
public:
void init(int i, int j);
void show();
};
inline void myclass::init (int i, int j)
{
a = i;
b = j;
}
inline void myclass::show()
{
cout << a << " " << b << "\n";
}
main()
{
myclass x;
x.init (10, 20);
x.show();
return 0;
}
- Class member functions can also be inline.
#include <iostream.h>
class myclass {
int a, b;
public:
// automatic inline
void init(int i, int j) {a=i; b=j;}
void show() {cout << a << " " << b << "\n";}
};
main()
{
myclass x;
x.init (10, 20);
x.show();
return 0;
}
- Define short functions within a class declaration.
- Automatically made into inline.
Parameterized Constructors
#include <iostream.h>
#include <string.h>
#define IN 1
#define CHECKED_OUT 0
class book {
char author[40];
char title[40];
int status;
public:
book (char *n, char *t, int s);
int get_status() {return status;}
void set_status(int s) {status = s;}
void show();
};
book::book (char *n, char *t, int s)
{
strcpy (author, n);
strcpy (title, t);
status = s;
}
void book::show()
{
cout << title << " by " << author;
cout << " is ";
if (status==IN)
cout << "in.\n";
else
cout << "out.\n";
}
main()
{
book b1 ("Twain", "Tom Sawyer", IN);
book b2 ("Melville", "Moby Dick", CHECKED_OUT);
b1.show();
b2.show();
return 0;
}
- Pass arguments to constructor functions.
- Typically used to initialize an object when it is created.
Static Data members
#include <iostream.h>
class shared {
static int a;
int b;
public:
void set(int i, int j) {a=i; b=j;}
void show();
};
int shared::a; // define a; thus allocate memory
void shared::show()
{
cout << "This is static a: " << a;
cout << "\nThis is non-static b: " << b;
cout << "\n";
}
main()
{
shared x, y;
x.set(1, 1); // set a to 1
x.show();
y.set(2, 2); // change a to 2
y.show();
x.show(); /* Here, a has been changed for both x and y
because a is shared by both objects. */
return 0;
}
Output:
This is static a: 1
This is non-static b: 1
This is static a: 2
This is non-static b: 2
This is static a: 2
This is non-static b: 1
- Only one copy of a static data member exists.
- All objects of the class will share that variable.
- A static data member exists before any object of its class is
created.
#include <iostream.h>
class client {
static int resource;
public:
int get_resource();
void free_resource() {resource = 0;}
};
int client::resource; // define resource
int client::get_resource()
{
if (resource)
return 0; // resource already in use
else {
resource = 1;
return 1; // resource allocated to this object
}
}
main()
{
client ob1, ob2;
if (ob1.get_resource())
cout << "ob1 has resource \n";
if (!ob2.get_resource())
cout << "ob2 denied resource \n";
ob1.free_resource(); // let someone else use it
if (ob2.get_resource())
cout << "ob2 can now use resource\n";
return 0;
}
- One of the most common uses of static member variables is to provide
access control to some shared resources.
- By using static member variables, any need for global variables is
virtually eliminated.
Static member functions
#include <iostream.h>
class client {
static int resource;
public:
static int get_resource();
void free_resource() {resource = 0;}
};
int client::resource; // define resource
int client::get_resource()
{
if (resource)
return 0; // resource already in use
else {
resource = 1;
return 1; // resource allocated to this object
}
}
main()
{
client ob1, ob2;
/* get_resource() is static, so may be called independent
of any object */
if (client::get_resource())
cout << "resource has been acquired\n";
if (!client::get_resource())
cout << "resource in use\n");
ob1.free_resource();
if (ob2.get_resource()) // can still call using object syntax
cout << "ob2 can now use resource\n";
return 0;
}
- Static member functions can only access other static members of the class.
- A static member function can be called directly, independent of any object
instance, using the class name and the scope resolution operator.
- Of course, can still be called in connection with an object instance.
- Can be used to "preinitialize" private static data before any object is
actually created.
Passing objects to functions
#include <iostream.h>
class myclass {
int i;
public:
myclass (int n);
~myclass ();
void set_i(int n) {i=n;}
int get_i() {return i;}
};
myclass::myclass (int n)
{
i = n;
cout << "Constructing " << i << "\n";
}
myclass::~myclass()
{
cout << "Destroying " << i << "\n";
}
void f(myclass ob);
|
|
main()
{
myclass o(1);
f(o);
cout << "This is i in main: ";
cout << o.get_i() << "\n";
return 0;
}
void f(myclass ob)
{
ob.set_i(2);
cout << "This is local i: " << ob.get_i();
cout << "\n";
}
|
Output:
Constructing 1
This is local i: 2
Destroying 2
This is i in main: 1
Destroying 1
- Objects are passed to functions through the use of the standard
call-by-value mechanism.
- That is, a copy of an object is made when it is passed to a function.
- Question: Should constructor and destructor called for the object copy?
- Constructor is not executed when the copy of the object is generated in a
function call.
- Destructor is executed when the copy is destroyed.
Object Assignment
#include <iostream.h>
class myclass {
int i;
public:
void set_i(int n) {i=n;}
int get_i() {return i;}
};
main()
{
myclass ob1, ob2;
ob1.set_i(99);
ob2 = ob1; // assign data from ob1 to ob2
cout << "This is ob2's i: " << ob2.get_i();
return 0;
}
- You can assign one object to another of the same class.
- This causes the data of the object on the right side to be copied into the
data of the object on the left.
- Bit-by-bit copy is used.
End of Tutorial II
|