[C++] Functions and Classes

A function is main construct of C/C++. Functions can be global or stay inside a class (member functions, aka methods).  Classes are the heart of Object Oriented. Declaring Classes in C++ is a little bit more difficult than C# or Java.  

 

1.Prototypes of a function

Unlike C# and Java, C/C++ needs to let the code know what functions are declared. That’s called prototypes.

There are 3 styles for declaring the prototype of a function.

  • return type + name of function
  • return type + name of function + types of parameters
  • return type + name of function + types and names of parameters
int func();
int func(int, double);
int func(int i, double d);

In C, you can use any of three styles. But in C++, you can only use the second and the third styles.

// int func();  // Error
int func(int, int);
int main()
{
  int a = func(2, 3);
  return (EXIT_SUCCESS);
}
int func(int a, int b)
{
  return a + b;
}

Do not forget that a semicolon is required at the end of each prototype.

 

2. Class Prototypes

The basic syntax of a class prototype is like this:

class class_name
{
Access_Specifier:
   data_member;
   function();
};

There are 3 access specifiers:

  • private: accessed only by other members of the class
  • protected: accessed by other members of the class and derived classes(inheritance)
  • public: allow functions or data to be accessible to other parts of the program
class MyRectangle
{
private:
  int width, height;
public:
  int size();
};

The class prototype also ends with a semicolon. Without it, you will get an error during compilation.

 

3. Constructors

When an instance of a class comes into scope, a special function called the constructor executes. Usually the constructor function is used for initialization. The constructor functions always have the same name as the class definition and they specify no return value. If you don’t provide any constructors, the compiler provides a public default constructor, which usually does nothing.

Constructors can be overloaded and also used with default values.

class MyRectangle
{
public:
  MyRectangle(void);
  MyRectangle(int wd, int ht=1);
};

MyRectangle::MyRectangle(void)
{
  width = 1;
  height = 1;
}

MyRectangle::MyRectangle(int wd, int ht)
{
  width = wd;
  height = ht;
}

But you need to be careful with constructors. Sometimes, the compiler cannot figure out which constructor should be called because of ambiguity. Let’s see the following example.

MyRectangle(void);
MyRectangle(int wd=10, int ht=10);

There are 2 constructors. If you create an object “MyRectangle rec;” which constructor should be called? Both constructors can be called. The compiler will create an error “‘MyRectangle::MyRectangle’ : ambiguous call to overloaded function”.

 

4. Parameter Initialization List

The main purpose of a constructor is to initialize the member variables. You can initialize the member variables using constructor’s parameter lists. Reference data members must be initialized with the way.

class MyRectangle
{
public:
  MyRectangle(void);
};

MyRectangle::MyRectangle(int wd, int ht)
  : width(wd), height(ht)
{
}

 

5. Copy Constructors

When an object is copied, the bitwise copy (bit-by-bit copy) of the object is made. The object copy is occurred when an object is passed to a function as a parameter or is returned by a function.

In most cases,  bitwise-copy can be ok. But in some cases, it causes the trouble. The most notorious case is that the object has a reference(pointer) to another object. When this kind of object is copied, the pointer is copied too. When one object is destroyed, the linked object can be destroyed too. Now the other object cannot refer to the linked object.

Copy constructors allow you to control what occurs when a copy of an object is made.

class_name (const class_name &obj) { … }

class MyPoint
{
public:
  int *p;
  MyPoint(int i); // normal constructor
  MyPoint(const MyPoint &obj); // copy constructor
  ~MyPoint(); // destructor
  int GetVal() { return *p; }
};

MyPoint::MyPoint(int i)
{
  p = new int(i);
  cout << "Inside the normal constructor: val = " << i << endl;
}

MyPoint::MyPoint(const MyPoint &obj)
{
  p = new int(*obj.p); // create a new memory
  cout << "Inside the copy constructor: val = " << *p << endl;
}

MyPoint::~MyPoint()
{
  cout << "Inside the destructor" << endl;
  delete p;
}

void DisplayMyPoint(MyPoint p)
{
  cout << "p = " << p.GetVal() << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
  MyPoint *p1 = new MyPoint(10);
  DisplayMyPoint(*p1);
  cout << "p = " << p1->GetVal() << endl; // this will not work without a copy constructor
  delete p1;

  return (EXIT_SUCCESS);
}

If you run this code, you will see the destructor is called twice.

Now comment the copy constructor and run the application again. Viola! You will see the garbage value from the call “p1->GetVal()” or the application will be crashed.

 

6. Destructors

When a class Object goes out of scope, destructor function is called.

The destructor’s name is always the name of the class with a tilde character(~) as a prefix. Only one destructor exists for a class.

 

7. Static Members

You can declare a member of a class as a static, in which case only one instance of it exists. Static members work such as they are in the global scope.

class Adder {
public :
  static int count; // static member
  static int add (int a, int b)
  {
    count++;
    return a+b;
  }
  static void printCount()
  {
     cout << "Counter :  how many times do you use adder function ? " << count << endl;
  }
};

int Adder::count=0;  // initialize the static member

int _tmain(int argc, _TCHAR* argv[])
{
  Adder::printCount(); // 0

  cout << " 2 + 3 = " << Adder::add(2,3) << endl;
  Adder::printCount(); // 1

  cout << " 4 + 5 = " << Adder::add(4,5) << endl;
  Adder::printCount(); // 2

  cout << " 6 + 7 = " << Adder::add(6,7) << endl;
  Adder::printCount(); // 3

  cout << " 8 + 9 = " << Adder::add(8,9) << endl;
  Adder::printCount(); // 4

  return (EXIT_SUCCESS);
}

 

8. this Pointer

The this pointer points to the object for which the member function is currently executing.

 

9. Examples

Sample code: MyRectangle class – Class Definition,  Constructors with parameter initialization list

// MyRectangle.h file
#pragma once
class MyRectangle
{
public:
  MyRectangle(void);
  MyRectangle(int wd);
  MyRectangle(int wd, int ht);
  ~MyRectangle(void);
public:
  int width, height;
public:
  int size();
};
// MyRectangle.cpp file
#include "MyRectangle.h"

MyRectangle::MyRectangle(void) : width(1), height(1) {}
MyRectangle::MyRectangle(int wd) : width(wd), height(1) {}
MyRectangle::MyRectangle(int wd, int ht) : width(wd), height(ht) {}
MyRectangle::~MyRectangle(void)  {}

int MyRectangle::size()
{
  return this->width * this->height;
}
#include "MyRectangle.h"

using namespace std;
int main()
{
  MyRectangle rec(10,20);
  cout << "Width = " << rec.width << ", Height  =" << rec.height << endl; // 10, 20
  cout << "Size = " << rec.size() << endl; // 200
  return (EXIT_SUCCESS);
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s