C++ Inline Functions,Constructors, Distructors and Unions








Inline Member Functions


A member function can also be defined as an inline just as global functions. An inline function as a member function improves the efficiency considerably. A member function is defined to be inline by inserting the keyword inline before its definition.class Student
{
Private:
string Fullname;

public:
void SetName (string);

};
inline void Student::SetName (string name)
{
FullName=name;
}

Alternatively and the easier way of defining a member function as inline is to include its definition inside the class. As in;

	class Student
	{
	Private:
	string Fullname;
	public:
	void Student::SetName (string name)
	{
	FullName=name;
	}
 
	};

Constructors

Constructors are member functions used to define and initialize objects of a class and sometimes to obtain resources such as memory, or a mutex or lock on a shared resource such as a hardware device. Actually by default, a compiler generates a constructor if it none is explicitly defined in a class. However if any constructor is written for the class, the compiler will not generate a default constructor. A default constructor has no arguments and is used to initiate all objects by default. It is important to remember that once a constructor is explicitly defined, a default constructor should be defined as well. A constructor must have same name as the class itself and cannot have an explicit return type. For example;

	class Student
	{
	Private:
	string Fullname;
	public:

	Student (string HerName){SetName(Hername);	// Constructor that initialises data member FullName
	}
	
	void SetName (string name)
	{
	FullName=name;
	}
 
	};

Once a constructor is explicitly included, objects of the class must be initialised at once as their declared and in correspondence with the form of the constructor. If a constructor requires arguments, they must be included in the initialisation of the object being instantiated. For Example;

#include<iostream>
                       #include<string>
                        using namespace std;
		
			class Student
			{
			private:
				string FullName;
			public:
				Student (string HerName){SetName(HerName);
			}
			void SetName (string name)
			{
				FullName=name;
			}
 
			};

			int main()
			{
				string StudentName("Molly Mweru");
				cout<<" The student’s name is "<<StudentName<<endl;
				return 0;
			}

Output:

	The student’s name is Molly Mweru

A class can contain more than one constructor. This must follow the principles of overloading of all functions i.e. each constructor must have a unique signature. For example;

			#include<iostream>
			#include<string>
			using namespace std;
		
			class Student
			{
			private:
				string FullName;
				int Age;
			public:
				Student (string HerName){SetName(HerName);
			}
				Student (int HerAge){Age=HerAge;
			}
				void SetName (string name) {	FullName=name;}
				int GetAge () {	return Age; }
				string GetName();
			};

				string Student::GetName() {	return FullName; }
	
			int main()
			{
				Student StudentName("Molly Mweru");
				Student StudentAge(25);
				cout<<" The student’s name is "<<StudentName.GetName()<<" and she is "<<StudentAge.GetAge()<<endl;
			
				return 0;
			}

Output :

The student’s name is Molly Mweru and she is 25

An object’s constructor is applied when the object is instantiated but also depending on the object’s scope. For a global object, it is created as soon as program execution commences while an automatic object is created when its scope is entered. Dynamic objects are created when the new operator is applied. A constructor for automatic variables is called each time the execution reaches a point where the variable is defined. For a static variable, its constructor is called once when execution reaches a point where the variable is defined. The constructor for a global variable is called as soon the program begins even before Main() is executed.

Destructors


Destructors work in the opposite of constructors. While constructors do initialize created objects, destructors clean up objects just before they are destroyed. An object's destructor is called whenever an object goes out of scope or when the "delete" operator is called on a pointer to the object. The purpose of the destructor is clean up. It is used to free memory and to release any locks or mutexes on system resources. Like a constructor, a destructor has the same name as the class itself, but is preceded with a ~ symbol. It does not take any arguments and has no explicit return type. A class can only have one destructor.


A destructor for an automatic variable is called at point when the variable goes out of scope during execution. However, if the program terminates with a call to function exit or abort, the distractor for automatic variables will not be called. For a static variable the destructor is called when Main() terminates or when the program calls the inbuilt function exit but not function abort. Global variables are destroyed in a reverse order they are created.

Follow the example below, which utilises both the concept of constructor and distractor calls.

			#include<iostream>
			#include<string>
			using namespace std;

			class Student
			{
			private:
				char regNo;
				int form; 
				string Fullname;
				int Age;

			public:
				Student();//Default Constructor

				Student (char, int, string, int);
				~Student();		//distructor
				void SetName (string);
			};

			Student::Student (char No, int level, string HerName, int HerAge)
			{ 
				regNo=No; 
				form=level; 
				SetName(HerName); 
				Age=HerAge; 
				cout<<"Constructor call to initialise form Levelfor RegNo  "<<regNo<<", form level: "<<form<<endl;
				cout<<"Constructor call to initialise name for RegNo "<<regNo<<", name: "<<Fullname<<endl;
				cout<<"Constructor call to initialise age for RegNo "<<regNo<<", age: "<<Age<<endl;
			}	
		
			Student::~Student()
			{
				cout<<"\nStudent distructor is called for RegNo "<<regNo<<endl;
				cout<<"Cleaning form Level for RegNo "<<regNo<<", form level: "<<form<<endl;
				cout<<"Cleaning name for RegNo "<<regNo<<", name: "<<Fullname<<endl;
				cout<<"Cleaning age for RegNo "<<regNo<<", age: "<<Age<<endl;
				cout<<"Distructor finishes for RegNo "<<regNo<<endl;
			}

			void Student::SetName (string name) 

			{
				Fullname=name;
			}

			Student one ('1',1,"Mariam Nike", 12);	// global variable

			int main()
			{

				cout<<"\n Main() begins to execute "<<endl;

				static Student Two('3',3,"Naima Niye", 13);

				Student three('4',4,"Nick Nuye", 15);
	
				cout<<" Main()ends execution "<<endl;

				return 0;
			}

Output:

			Constructor call to initialise form Levelfor RegNo  1, form level: 1
			Constructor call to initialise name for RegNo 1, name: Mariam Nike
			Constructor call to initialise age for RegNo 1, age: 12

		 Main() begins to execute 
			Constructor call to initialise form Levelfor RegNo  3, form level: 3
			Constructor call to initialise name for RegNo 3, name: Naima Niye
			Constructor call to initialise age for RegNo 3, age: 13
			Constructor call to initialise form Levelfor RegNo  4, form level: 4
			Constructor call to initialise name for RegNo 4, name: Nick Nuye
			Constructor call to initialise age for RegNo 4, age: 15

		Main()ends execution 
			Student distructor is called for RegNo 4
			Cleaning form Level for RegNo 4, form level: 4
			Cleaning name for RegNo 4, name: Nick Nuye
			Cleaning age for RegNo 4, age: 15
			Distructor finishes for RegNo 4

			Student distructor is called for RegNo 3
			Cleaning form Level for RegNo 3, form level: 3
			Cleaning name for RegNo 3, name: Naima Niye
			Cleaning age for RegNo 3, age: 13
			Distructor finishes for RegNo 3

			Student distructor is called for RegNo 1	
			Cleaning form Level for RegNo 1, form level: 1
			Cleaning name for RegNo 1, name: Mariam Nike
			Cleaning age for RegNo 1, age: 12
			Distructor finishes for RegNo 1


Note the order in which the constructors have been called. Student object one is a global variable and so its constructor was called as soon the program begun even before Main() is executed. Constructors for static variable two and automatic variable three were called when execution reached at their point where they are defined in main(). But observe how the distractors are called. The destructor for the automatic variable three is called first, follows by that of the static variable three and global variable one is destroyed last.

Utility Functions


Utility functions are private member functions of the class that support the operations of the class public member functions. Utility member functions are not meant to be used by the clients of the class. However they can be used by the friends of the class. Follow the example below;

			#include<iostream>
			#include<string>
			using namespace std;
			
			class sales
			{
			private:
				int Qty;
				int Price;
				int Days;
				
				int TotalSales()
				{  
				int TotalQty=Qty*Days; //utility member function
	             		return TotalQty*Price;
				}
			public:
				sales(int q, int p, int d)	{	Qty=q; Price=p; Days=d;	}
				int AvSales();
			};

			int sales::AvSales()
			{
				int TotalQty=Qty*Days;

				return TotalSales()/TotalQty; //AvSales makes use of the utility member function
			}

			int main()
			{
				sales WeekSales(20,50,7);
				cout<<"Average day sales for last week are $"<<WeekSales.AvSales();

				return 0;
			}

Output:Average sales for last week are $50

Constant Objects and Constant Member functions


We use a key const to specify that is not modifiable and any attempt to modify it should result into an error. Both data and member functions can be declared as constant. A const key word is used in member function by inserting it after the closing parenthesis of the parameter list. If an object is declared as a constant, it cannot be used to access non constant member function. Constant data members must be initialised using the classmember initializer. Follow the example below ;

			#include<iostream>
			using namespace std;

			class sales
			{
			private:
				int Qty;
				const int Price;
				int Days;
				int TotalSales()	
				{  
					int TotalQty=Qty*Days; //utility member function
 			                return TotalQty*Price;
        		        }
			public:

				//using a member initializer to initialize constant variable Price
				sales(int q, int p, int d):Price(p)	{	Qty=q; Days=d;	}
	
				sales(int P):Price(P){	}

			void AvSales();
				void nextPrice() const {	cout<<"\nThe sale price for next week is $"<<Price;	}
			};

			void sales::AvSales()
			{
				int TotalQty=Qty*Days;
		
				//AvSales makes use of the utility member function
				cout<<"Average day sales for last week are $"<<TotalSales()/TotalQty; 
			}

			int main()
			{
				sales WeekSales(20,50,7);
				const sales PriceNextWk(15);
				WeekSales.AvSales();
				PriceNextWk.nextPrice();

				return 0;
			}

Output:

Average day sales for last week are $50
The sale price for next week is $15

Note the way we initialized constant data member “price”. We initialized it using the member initializer list which appears between the constructors closing parenthesis of the constructors parameter list and the beginning the body of the constructor and separated by a semicolon(:). A member is initialized by including the name of the data member followed a members initial value enclosed in a pair of parenthesizes. Please note once a constant member has been initially initialized it cannot be assigned another value. In other words from the time the constructor is initialized to the time a distractor clears it, no new assignment can be made to a constant member.

Friends of a class


A friend is a function that is enabled to access the non-public members of a class by explicitly declaring a function with in a class as a friend. Use of class friends improves implementation efficiency. Below is an example of a friend function in a class.
			#include<iostream>
			using namespace std;

			class polygon
			{
				friend void RecArea(polygon);
				
				int width;
				int height;

			public:
				polygon(int w, int h){width=w; height=h;}
				void TriArea();
			};

			void polygon::TriArea()
			{
				cout<<"The area of a triangle is "<<width*height/2<<endl;
			}

			void RecArea(polygon sides)
			{
				cout<<"The area of a Rectangle is "<<sides.width*sides.height*2<<endl;
			}

			int main()
			{
				polygon itsSides(5,4);
				itsSides.TriArea();
				RecArea(itsSides);
				
				return 0;
			}

Output:The area of a triangle is 10
The area of a Rectangle is 40

The inclusion of a friend function in a class does not make it a member of that class. It does not matter which point in a class a friend function is declared, whether it is under the private, protected, or the public section, it has the same meaning.

The extreme case of having all member functions of a class A as friends of another class B can be expressed in an abbreviated form:

Unions

A union is a form of a class whose data members are mapped to the same address within its object. In other words members of a union share the same data space, in contrast to a class or struct whose data members are stored sequentially in a memory such that each precedes the other in order of declaration at an offset determined by the data types of the members.

The member-list of a union represents the kinds of data that the union can contain. The size of an object of a union is the size of its largest data member. Therefore, a union requires enough storage to hold the largest member in its member-list. Unions are mainly used in situations where an object may assume different type values, but only one at a time. Union may be useful when it is necessary to work with different representation of same binary data, that is, if you want to use different data types at the same time, using same block of memory.

To create a union, use the union keyword following the same syntax applied for a class. Follow the example below

			#include<iostream>
			#include<string>
			using namespace std;

			union Client   

			{

				char Gender;

				int Age;

				float Height;

			};

			int main()

			{
	
				Client Patient;

				Patient.Gender='M';
				Cout<<"The sex of the patient is "<<Patient.Gender;         

				Patient.Age = 22;
				cout<<",he is "<< Patient.Age;
          
				Patient.Height=54.6;
          
				cout<<" years old and "<<Patient.Height<<" ft tall. "<<endl;
	

				return 0;

			}

Output:

The sex of the patient is M,he is 22 years old and 54.6 ft tall. 

Be cautious when using unions. Because members share the same memory, assignment of a value to one union member affects the other union members. A write to one member that is followed by a read from another member is sometimes, but not always, an implicit cast. As you can see we print the value of each member immediately after assigning it a value. If we had assigned values to all the members at once, on printing the results would be unpredictable. This is because all members use the same memory space, which cannot accommodate all member values at the same time.

Main differences between C++ union and a class

  • Unions cannot have virtual functions while classes can.
  • Unlike classes Union cannot act as a base class.
  • Unions cannot have static members but classes can.
  • An object of a class with a constructor or a destructor or a user-defined assignment operator can't be a member of union.
PREV:Introduction to Structures NEXT:Introduction to Operator Overloading