Learn About C++ Classes and Objects

01
of 09

Starting With C++ Classes

Using all the latest tech
PeopleImages.com / Getty Images

Objects are the biggest difference between C++ and C. One of the earliest names for C++ was C with Classes.

Classes and Objects

A class is a definition of an object. It's a type just like int. A class resembles a struct with just one difference: all struct members are public by default. All classes members are private.

Remember: A class is a type, and an object of this class is just a variable.

Before we can use an object, it must be created. The simplest definition of a class is

 class name {
 // members
 }
 

This example class below models a simple book. Using OOP lets you abstract the problem and think about it and not just arbitrary variables.

 // example one
 #include 
 #include 
 
 class Book
 {
 int PageCount;
 int CurrentPage; 
 public:
 Book( int Numpages) ; // Constructor
 ~Book(){} ; // Destructor
 void SetPage( int PageNumber) ;
 int GetCurrentPage( void ) ;
 }; 
 
 Book::Book( int NumPages) {
 PageCount = NumPages;
 }
 
 void Book::SetPage( int PageNumber) {
 CurrentPage=PageNumber;
 }
 
 int Book::GetCurrentPage( void ) {
 return CurrentPage;
 }
 
 int main() {
 Book ABook(128) ;
 ABook.SetPage( 56 ) ;
 std::cout << "Current Page " << ABook.GetCurrentPage() << std::endl;
 return 0;
 }
 

All the code from class book down to the int Book::GetCurrentPage(void) { function is part of the class. The main() function is there to make this a runnable application.

02
of 09

Understanding the Book Class

In the main() function a variable ABook of type Book is created with the value 128. As soon as execution reaches this point, the object ABook is constructed. On the next line the method ABook.SetPage() is called and the value 56 assigned to the object variable ABook.CurrentPage. Then cout outputs this value by calling the Abook.GetCurrentPage() method.

When execution reaches the return 0; the ABook object is no longer needed by the application. The compiler generates a call to the destructor.

Declaring Classes

Everything between Class Book and the } is the class declaration. This class has two private members, both of type int. These are private because the default access to class members is private.

The public: directive tells the compiler that accesses from here on is public. Without this, it would still be private and prevent the three lines in the main() function from accessing Abook members. Try commenting the public: line out and recompiling to see the ensuing compile errors.

This line below declares a Constructor. This is the function called when the object is first created.

 Book( int Numpages) ; // Constructor 

It is called from the line

 Book ABook(128) ; 

This creates an object called ABook of type Book and calls the Book() function with the parameter 128.

03
of 09

More About the Book Class

In C++, the constructor always has the same name as the class. The constructor is called when the object is created and is where you should put your code to initialize the object.

In Book The next line after the constructor the destructor. This has the same name as the constructor but with a ~ (tilde) in front of it. During the destruction of an object, the destructor is called to tidy up the object and ensure that resources such as memory and file handle used by the object are released.

Remember : A class xyz has a constructor function xyz() and destructor function ~xyz(). Even if you don't declare then the compiler will silently add them.

The destructor is always called when the object is terminated. In this example, the object is implicitly destroyed when it goes out of scope. To see this, modify the destructor declaration to this.

 ~Book(){ std::cout << "Destructor called";} ; // Destructor 

This is an inline function with code in the declaration. Another way to inline is adding the word inline.

 inline ~Book() ; // Destructor
 

and add the destructor as a function like this.

 inline Book::~Book ( void ) { 
 	std::cout << "Destructor called";
 }
 

Inline functions are hints to the compiler to generate more efficient code. They should only be used for small functions, but if used in appropriate places such as inside loops can make a considerable difference in performance.

04
of 09

Learn About Writing Class Methods

Best practice for objects is to make all data private and access it through functions known as accessor functions. SetPage() and GetCurrentPage() are the two functions used to access the object variable CurrentPage.

Change the class declaration to struct and recompile. It still compiles and runs correctly. Now the two variables PageCount and CurrentPage are publicly accessible. Add this line after the Book ABook(128), and it will compile.

 ABook.PageCount =9;
 

If you change struct back to class and recompile, that new line will no longer compile as PageCount is now private again.

The :: Notation

After the body of Book Class declaration, there are the four definitions of the member functions. Each is defined with the Book:: prefix to identify it as belonging to that class. :: is called the scope identifier. It identifies the function as being part of the class. This is obvious in the class declaration but not outside it.

If you have declared a member function in a class you must provide the body of the function in this way. If you wanted the Book class to be used by other files then you might move the declaration of book into a separate header file perhaps called book.h. Any other file could then include it with

 #include "book.h" 
05
of 09

Learn About Inheritance and Polymorphism

This example will demonstrate inheritance. This is a two class application with one class derived from another.

 #include 
 #include 
 
 class Point
 {
 
 int x,y;
 public:
 Point(int atx,int aty ) ; // Constructor
 inline virtual ~Point() ; // Destructor
 virtual void Draw() ;
 }; 
 
 class Circle : public Point {
 
 	int radius;
 public:
 	Circle(int atx,int aty,int theRadius) ;
 	inline virtual ~Circle() ;
 	virtual void Draw() ;
 };
 
 
 Point ::Point(int atx,int aty) {
 	x = atx;
 	y = aty;
 }
 
 inline Point::~Point ( void ) { 
 	std::cout << "Point Destructor called";
 }
 
 void Point::Draw( void ) {
 	std::cout << "Point::Draw point at " << x << " " << y << std::endl;
 }
 
 
 Circle::Circle(int atx,int aty,int theRadius) : Point(atx,aty) {
 	radius = theRadius;
 }
 
 inline Circle::~Circle() {
 	std::cout << "Circle Destructor called" << std::endl;
 }
 
 void Circle::Draw( void ) {
 	Point::Draw() ;
 std::cout << "circle::Draw point " << " Radius "<< radius << std::endl;
 }
 
 int main() {
 	Circle ACircle(10,10,5) ;
 	ACircle.Draw() ;
 	return 0;
 }
 

The example has two classes Point and Circle, modeling a point and a circle. A Point has x and y coordinates. The Circle class is derived from the Point class and adds a radius. Both classes include a Draw() member function. To keep this example short the output is just text.

06
of 09

Learn About Inheritance

The class Circle is derived from the Point class. This is done in this line:

 class Circle : Point {
 

Because it is derived from a base class (Point), Circle inherits all the class members.

 Point(int atx,int aty ) ; // Constructor
 inline virtual ~Point() ; // Destructor
 virtual void Draw() ;
 
 Circle(int atx,int aty,int theRadius) ;
 inline virtual ~Circle() ;
 virtual void Draw() ;
 

Think of the Circle class as the Point class with an extra member (radius). It inherits the base class Member functions and private variables x and y.

It cannot assign or use these except implicitly because they are private, so it has to do it through the Circle constructor's Initializer list. This is something you should accept, for now, I'll come back to initializer lists in a future tutorial.

In the Circle Constructor, before theRadius is assigned to the radius, the Point part of Circle is constructed through a call to Point's constructor in the initializer list. This list is everything between the: and the { below.

 Circle::Circle(int atx,int aty,int theRadius) : Point(atx,aty) 
 

Incidentally, constructor type initialization can be used for all built-in types.

 int a1(10) ;
 int a2=10 ;
 

Both do the same.

07
of 09

What Is Polymorphism?

Polymorphism is a generic term that means 'many shapes'. In C++ the simplest form of Polymorphism is overloading of functions, for instance, several functions called SortArray( arraytype ) where sortarray might be an array of ints or doubles.

We're only interested here though in the OOP form of polymorphism. This is done by making a function (e.g. Draw() ) virtual in the base class Point and then overriding it in the derived class Circle.

Although the function Draw() is virtual in the derived class Circle, this isn't actually needed- it's a reminder to me that this it is virtual. If the function in a derived class matches a virtual function in the base class on name and parameter types, it is automatically virtual.

Drawing a point and drawing a circle are two very different operations with only the coordinates of the point and circle in common. So it's important that the correct Draw() is called. How the compiler manages to generate code that gets the right virtual function will be covered in a future tutorial.

08
of 09

Learn About C++ Constructors

Constructors

A constructor is a function that initializes the members of an object. A constructor only knows how to build an object of its own class.

Constructors aren't automatically inherited between the base and derived classes. If you don't supply one in the derived class, a default will be provided but this may not do what you want.

If no constructor is supplied then a default one is created by the compiler without any parameters. There must always be a constructor, even if it is the default and empty. If you supply a constructor with parameters then a default will NOT be created.

Some points about constructors

  • Constructors are just functions with the same name as the class.
  • Constructors are intended to initialize the members of the class when an instance of that class is created.
  • Constructors are not called directly (except through initializer lists)
  • Constructors are never virtual.
  • Multiple constructors for the same class can be defined. They must have different parameters to distinguish them.

There is a lot more to learn about constructors, for instance, default constructors, assignment and copy constructors and these will be discussed in the next lesson.

09
of 09

Tidying Up - C++ Destructors

A destructor is a class member function that has the same name as the constructor (and the class ) but with a ~ (tilde) in front.

 ~Circle() ;
 

When an object goes out of scope or more rarely is explicitly destroyed, its destructor is called. For instance, if the object has dynamic variables, such as pointers then those need to be freed and the destructor is the appropriate place.

Unlike constructors, destructors can and should be made virtual if you have derived classes. In the Point and Circle classes example, the destructor is not needed as there is no cleanup work to be done, it just serves as an example. Had there been dynamic member variables (e.g. pointer) then those would have required freeing to prevent memory leaks.

Also when the derived class adds members that require tidying up, virtual destructors are needed. When virtual, the most derived class destructor is called first, then its immediate ancestor's destructor is called, and so on up to the base class.

In our example,

 ~Circle() ;
 then
 ~Point() ;
 

The base classes destructor is called last.

This completes this lesson. In the next lesson, learn about default constructors, copy constructors, and assignment.