c++ programming
The basics of C++
This tutorial series is designed for everyone: even if you've never programmed before or if you have extensive experience programming in other languages and want to expand into C++! It is for everyone who wants the feeling of accomplishment from a working program.
What do I mean? C++ is a programming language--it will allow you to control your computer, making it do what you want it to do. This programming tutorial series is all about helping you take advantage of C++.
Getting Set Up - C++ CompilersThe very first thing you need to do, before starting out in C++, is to make sure that you have a compiler. What is a compiler, you ask? A compiler turns the program that you write into an executable that your computer can actually understand and run. If you're taking a course, you probably have one provided through your school. If you're starting out on your own, your best bet is to use Code::Blocks with MinGW. If you're on Linux, you can use g++, and if you're on Mac OS X, you can use XCode. (If you are stuck using an older compiler, such as Turbo C++, you'll need to read this page on compatibility issues.) If you haven't yet done so, go ahead and get a compiler set up--you'll need it for the rest of the tutorial.Intro to the C++ LanguageA C++ program is a collection of commands, which tell the computer to do "something". This collection of commands is usually called C++ source code, source code or just code. Commands are either "functions" or "keywords". Keywords are a basic building block of the language, while functions are, in fact, usually written in terms of simpler functions--you'll see this in our very first program, below. (Confused? Think of it a bit like an outline for a book; the outline might show every chapter in the book; each chapter might have its own outline, composed of sections. Each section might have its own outline, or it might have all of the details written up.) Thankfully, C++ provides a great many common functions and keywords that you can use.
But how does a program actually start? Every program in C++ has one function, always named main, that is always called when your program first executes. From main, you can also call other functions whether they are written by us or, as mentioned earlier, provided by the compiler.
So how do you get access to those prewritten functions? To access those standard functions that comes with the compiler, you include a header with the #include directive. What this does is effectively take everything in the header and paste it into your program. Let's look at a working program:
#include <iostream>
using namespace std;
int main()
{
cout<<"HEY, you, I'm alive! Oh, and Hello World!\n";
cin.get();
}
Let's look at the elements of the program. The #include is a "preprocessor" directive that tells the compiler to put code from the header called iostream into our program before actually creating the executable. By including header files, you gain access to many different functions. For example, the cout function requires iostream. Following the include is the statement, "using namespace std;". This line tells the compiler to use a group of functions that are part of the standard library (std). By including this line at the top of a file, you allow the program to use functions such as cout. The semicolon is part of the syntax of C++. It tells the compiler that you're at the end of a command. You will see later that the semicolon is used to end most commands in C++.
The next important line is int main(). This line tells the compiler that there is a function named main, and that the function returns an integer, hence int. The "curly braces" ({ and }) signal the beginning and end of functions and other code blocks. You can think of them as meaning BEGIN and END.
The next line of the program may seem strange. If you have programmed in another language, you might expect that print would be the function used to display text. In C++, however, the cout object is used to display text (pronounced "C out"). It uses the << symbols, known as "insertion operators", to indicate what to output. cout<< results in a function call with the ensuing text as an argument to the function. The quotes tell the compiler that you want to output the literal string as-is. The '\n' sequence is actually treated as a single character that stands for a newline (we'll talk about this later in more detail). It moves the cursor on your screen to the next line. Again, notice the semicolon: it is added onto the end of most lines, such as function calls, in C++.
The next command is cin.get(). This is another function call: it reads in input and expects the user to hit the return key. Many compiler environments will open a new console window, run the program, and then close the window. This command keeps that window from closing because the program is not done yet because it waits for you to hit enter. Including that line gives you time to see the program run.
Upon reaching the end of main, the closing brace, our program will return the value of 0 (and integer, hence why we told main to return an int) to the operating system. This return value is important as it can be used to tell the OS whether our program succeeded or not. A return value of 0 means success and is returned automatically (but only for main, other functions require you to manually return a value), but if we wanted to return something else, such as 1, we would have to do it with a return statement:
#include <iostream>
using namespace std;
int main()
{
cout<<"HEY, you, I'm alive! Oh, and Hello World!\n";
cin.get();
return 1;
}
The final brace closes off the function. You should try compiling this program and running it. You can cut and paste the code into a file, save it as a .cpp file. Our Code::Blocks tutorial actually takes you through creating a simple program, so check it out if you're confused.
If you are not using Code::Blocks, you should read the compiler instructions for information on how to compile.
Once you've got your first program running, why don't you try playing around with the cout function to get used to writing C++?
An Aside on Commenting Your ProgramsAs you are learning to program, you should also start to learn how to explain your programs (for yourself, if no one else). You do this by adding comments to code; I'll use them frequently to help explain code examples.
When you tell the compiler a section of text is a comment, it will ignore it when running the code, allowing you to use any text you want to describe the real code. To create a comment use either //, which tells the compiler that the rest of the line is a comment, or /* and then */ to block off everything between as a comment. Certain compiler environments will change the color of a commented area, but some will not. Be certain not to accidentally comment out code (that is, to tell the compiler part of your code is a comment) you need for the program. When you are learning to program, it is useful to be able to comment out sections of code in order to see how the output is affected.
User interaction and Saving Information with VariablesSo far you've learned how to write a simple program to display information typed in by you, the programmer, and how to describe your program with comments. That's great, but what about interacting with your user? Fortunately, it is also possible for your program to accept input. The function you use is known as cin, and is followed by the insertion operator >>.
Of course, before you try to receive input, you must have a place to store that input. In programming, input and data are stored in variables. There are several different types of variables which store different kinds of information (e.g. numbers versus letters); when you tell the compiler you are declaring a variable, you must include the data type along with the name of the variable. Several basic types include char, int, and float.
A variable of type char stores a single character, variables of type int store integers (numbers without decimal places), and variables of type float store numbers with decimal places. Each of these variable types - char, int, and float - is each a keyword that you use when you declare a variable.What's with all these variable types?Sometimes it can be confusing to have multiple variable types when it seems like some variable types are redundant (why have integer numbers when you have floats?). Using the right variable type can be important for making your code readable and for efficiency--some variables require more memory than others. Moreover, because of the way the numbers are actually stored in memory, a float is "inexact", and should not be used when you need to store an "exact" integer value.
Declaring Variables in C++To declare a variable you use the syntax "type <name>;". Here are some variable declaration examples:1
2
3
int x;
char letter;
float the_float;
It is permissible to declare multiple variables of the same type on the same line; each one should be separated by a comma.1
int a, b, c, d;
If you were watching closely, you might have seen that declaration of a variable is always followed by a semicolon (note that this is the same procedure used when you call a function).Common Errors when Declaring Variables in C++If you attempt to use a variable that you have not declared, your program will not be compiled or run, and you will receive an error message informing you that you have made a mistake. Usually, this is called an undeclared variable.Case SensitivityNow is a good time to talk about an important concept that can easily throw you off: case sensitivity. Basically, in C++, whether you use uppercase or lowercase letters matters. The words Cat and cat mean different things to the compiler. In C++, all language keywords, all functions and all variables are case sensitive. A difference in case between your variable declaration and the use of the variable is one reason you might get an undeclared variable error.Using VariablesOk, so you now know how to tell the compiler about variables, but what about using them?
Here is a sample program demonstrating the use of a variable:
#include <iostream>
using namespace std;
int main()
{
int thisisanumber;
cout<<"Please enter a number: ";
cin>> thisisanumber;
cin.ignore();
cout<<"You entered: "<< thisisanumber <<"\n";
cin.get();
}
Let's break apart this program and examine it line by line. The keyword int declares thisisanumber to be an integer. The function cin>> reads a value into thisisanumber; the user must press enter before the number is read by the program. cin.ignore() is another function that reads and discards a character. Remember that when you type input into a program, it takes the enter key too. We don't need this, so we throw it away. Keep in mind that the variable was declared an integer; if the user attempts to type in a decimal number, it will be truncated (that is, the decimal component of the number will be ignored). Try typing in a sequence of characters or a decimal number when you run the example program; the response will vary from input to input, but in no case is it particularly pretty. Notice that when printing out a variable quotation marks are not used. Were there quotation marks, the output would be "You Entered: thisisanumber." The lack of quotation marks informs the compiler that there is a variable, and therefore that the program should check the value of the variable in order to replace the variable name with the variable when executing the output function. Do not be confused by the inclusion of two separate insertion operators on one line. Including multiple insertion operators on one line is perfectly acceptable and all of the output will go to the same place. In fact, you must separate string literals (strings enclosed in quotation marks) and variables by giving each its own insertion operators (<<). Trying to put two variables together with only one << will give you an error message, do not try it. Do not forget to end functions and declarations with a semicolon. If you forget the semicolon, the compiler will give you an error message when you attempt to compile the program.Changing and Comparing VariablesOf course, no matter what type you use, variables are uninteresting without the ability to modify them. Several operators used with variables include the following: *, -, +, /, =, ==, >, <. The * multiplies, the - subtracts, and the + adds. It is of course important to realize that to modify the value of a variable inside the program it is rather important to use the equal sign. In some languages, the equal sign compares the value of the left and right values, but in C++ == is used for that task. The equal sign is still extremely useful. It sets the left input to the equal sign, which must be one, and only one, variable equal to the value on the right side of the equal sign. The operators that perform mathematical functions should be used on the right side of an equal sign in order to assign the result to a variable on the left side.
Here are a few examples:
a = 4 * 6; // (Note use of comments and of semicolon) a is 24
a = a + 5; // a equals the original value of a with five added to it
a == 5 // Does NOT assign five to a. Rather, it checks to see if a equals 5.
The other form of equal, ==, is not a way to assign a value to a variable. Rather, it checks to see if the variables are equal. It is useful in other areas of C++; for example, you will often use == in such constructions as conditional statements and loops. You can probably guess how < and > function. They are greater than and less than operators.
For example:
a < 5 // Checks to see if a is less than five
a > 5 // Checks to see if a is greater than five
a == 5 // Checks to see if a equals five, for good measure
Comparing variables isn't really useful until you have some way of using the results--that's what lesson 2, on if statements is all about.
If you enjoyed this tutorial, check out the Cprogramming.com ebook, Jumping into C++. It contains all the information in this tutorial, plus much much more, in one convenient place, along with tons of sample code and practice problems. Buy Jumping into C++ today!
What do I mean? C++ is a programming language--it will allow you to control your computer, making it do what you want it to do. This programming tutorial series is all about helping you take advantage of C++.
Getting Set Up - C++ CompilersThe very first thing you need to do, before starting out in C++, is to make sure that you have a compiler. What is a compiler, you ask? A compiler turns the program that you write into an executable that your computer can actually understand and run. If you're taking a course, you probably have one provided through your school. If you're starting out on your own, your best bet is to use Code::Blocks with MinGW. If you're on Linux, you can use g++, and if you're on Mac OS X, you can use XCode. (If you are stuck using an older compiler, such as Turbo C++, you'll need to read this page on compatibility issues.) If you haven't yet done so, go ahead and get a compiler set up--you'll need it for the rest of the tutorial.Intro to the C++ LanguageA C++ program is a collection of commands, which tell the computer to do "something". This collection of commands is usually called C++ source code, source code or just code. Commands are either "functions" or "keywords". Keywords are a basic building block of the language, while functions are, in fact, usually written in terms of simpler functions--you'll see this in our very first program, below. (Confused? Think of it a bit like an outline for a book; the outline might show every chapter in the book; each chapter might have its own outline, composed of sections. Each section might have its own outline, or it might have all of the details written up.) Thankfully, C++ provides a great many common functions and keywords that you can use.
But how does a program actually start? Every program in C++ has one function, always named main, that is always called when your program first executes. From main, you can also call other functions whether they are written by us or, as mentioned earlier, provided by the compiler.
So how do you get access to those prewritten functions? To access those standard functions that comes with the compiler, you include a header with the #include directive. What this does is effectively take everything in the header and paste it into your program. Let's look at a working program:
#include <iostream>
using namespace std;
int main()
{
cout<<"HEY, you, I'm alive! Oh, and Hello World!\n";
cin.get();
}
Let's look at the elements of the program. The #include is a "preprocessor" directive that tells the compiler to put code from the header called iostream into our program before actually creating the executable. By including header files, you gain access to many different functions. For example, the cout function requires iostream. Following the include is the statement, "using namespace std;". This line tells the compiler to use a group of functions that are part of the standard library (std). By including this line at the top of a file, you allow the program to use functions such as cout. The semicolon is part of the syntax of C++. It tells the compiler that you're at the end of a command. You will see later that the semicolon is used to end most commands in C++.
The next important line is int main(). This line tells the compiler that there is a function named main, and that the function returns an integer, hence int. The "curly braces" ({ and }) signal the beginning and end of functions and other code blocks. You can think of them as meaning BEGIN and END.
The next line of the program may seem strange. If you have programmed in another language, you might expect that print would be the function used to display text. In C++, however, the cout object is used to display text (pronounced "C out"). It uses the << symbols, known as "insertion operators", to indicate what to output. cout<< results in a function call with the ensuing text as an argument to the function. The quotes tell the compiler that you want to output the literal string as-is. The '\n' sequence is actually treated as a single character that stands for a newline (we'll talk about this later in more detail). It moves the cursor on your screen to the next line. Again, notice the semicolon: it is added onto the end of most lines, such as function calls, in C++.
The next command is cin.get(). This is another function call: it reads in input and expects the user to hit the return key. Many compiler environments will open a new console window, run the program, and then close the window. This command keeps that window from closing because the program is not done yet because it waits for you to hit enter. Including that line gives you time to see the program run.
Upon reaching the end of main, the closing brace, our program will return the value of 0 (and integer, hence why we told main to return an int) to the operating system. This return value is important as it can be used to tell the OS whether our program succeeded or not. A return value of 0 means success and is returned automatically (but only for main, other functions require you to manually return a value), but if we wanted to return something else, such as 1, we would have to do it with a return statement:
#include <iostream>
using namespace std;
int main()
{
cout<<"HEY, you, I'm alive! Oh, and Hello World!\n";
cin.get();
return 1;
}
The final brace closes off the function. You should try compiling this program and running it. You can cut and paste the code into a file, save it as a .cpp file. Our Code::Blocks tutorial actually takes you through creating a simple program, so check it out if you're confused.
If you are not using Code::Blocks, you should read the compiler instructions for information on how to compile.
Once you've got your first program running, why don't you try playing around with the cout function to get used to writing C++?
An Aside on Commenting Your ProgramsAs you are learning to program, you should also start to learn how to explain your programs (for yourself, if no one else). You do this by adding comments to code; I'll use them frequently to help explain code examples.
When you tell the compiler a section of text is a comment, it will ignore it when running the code, allowing you to use any text you want to describe the real code. To create a comment use either //, which tells the compiler that the rest of the line is a comment, or /* and then */ to block off everything between as a comment. Certain compiler environments will change the color of a commented area, but some will not. Be certain not to accidentally comment out code (that is, to tell the compiler part of your code is a comment) you need for the program. When you are learning to program, it is useful to be able to comment out sections of code in order to see how the output is affected.
User interaction and Saving Information with VariablesSo far you've learned how to write a simple program to display information typed in by you, the programmer, and how to describe your program with comments. That's great, but what about interacting with your user? Fortunately, it is also possible for your program to accept input. The function you use is known as cin, and is followed by the insertion operator >>.
Of course, before you try to receive input, you must have a place to store that input. In programming, input and data are stored in variables. There are several different types of variables which store different kinds of information (e.g. numbers versus letters); when you tell the compiler you are declaring a variable, you must include the data type along with the name of the variable. Several basic types include char, int, and float.
A variable of type char stores a single character, variables of type int store integers (numbers without decimal places), and variables of type float store numbers with decimal places. Each of these variable types - char, int, and float - is each a keyword that you use when you declare a variable.What's with all these variable types?Sometimes it can be confusing to have multiple variable types when it seems like some variable types are redundant (why have integer numbers when you have floats?). Using the right variable type can be important for making your code readable and for efficiency--some variables require more memory than others. Moreover, because of the way the numbers are actually stored in memory, a float is "inexact", and should not be used when you need to store an "exact" integer value.
Declaring Variables in C++To declare a variable you use the syntax "type <name>;". Here are some variable declaration examples:1
2
3
int x;
char letter;
float the_float;
It is permissible to declare multiple variables of the same type on the same line; each one should be separated by a comma.1
int a, b, c, d;
If you were watching closely, you might have seen that declaration of a variable is always followed by a semicolon (note that this is the same procedure used when you call a function).Common Errors when Declaring Variables in C++If you attempt to use a variable that you have not declared, your program will not be compiled or run, and you will receive an error message informing you that you have made a mistake. Usually, this is called an undeclared variable.Case SensitivityNow is a good time to talk about an important concept that can easily throw you off: case sensitivity. Basically, in C++, whether you use uppercase or lowercase letters matters. The words Cat and cat mean different things to the compiler. In C++, all language keywords, all functions and all variables are case sensitive. A difference in case between your variable declaration and the use of the variable is one reason you might get an undeclared variable error.Using VariablesOk, so you now know how to tell the compiler about variables, but what about using them?
Here is a sample program demonstrating the use of a variable:
#include <iostream>
using namespace std;
int main()
{
int thisisanumber;
cout<<"Please enter a number: ";
cin>> thisisanumber;
cin.ignore();
cout<<"You entered: "<< thisisanumber <<"\n";
cin.get();
}
Let's break apart this program and examine it line by line. The keyword int declares thisisanumber to be an integer. The function cin>> reads a value into thisisanumber; the user must press enter before the number is read by the program. cin.ignore() is another function that reads and discards a character. Remember that when you type input into a program, it takes the enter key too. We don't need this, so we throw it away. Keep in mind that the variable was declared an integer; if the user attempts to type in a decimal number, it will be truncated (that is, the decimal component of the number will be ignored). Try typing in a sequence of characters or a decimal number when you run the example program; the response will vary from input to input, but in no case is it particularly pretty. Notice that when printing out a variable quotation marks are not used. Were there quotation marks, the output would be "You Entered: thisisanumber." The lack of quotation marks informs the compiler that there is a variable, and therefore that the program should check the value of the variable in order to replace the variable name with the variable when executing the output function. Do not be confused by the inclusion of two separate insertion operators on one line. Including multiple insertion operators on one line is perfectly acceptable and all of the output will go to the same place. In fact, you must separate string literals (strings enclosed in quotation marks) and variables by giving each its own insertion operators (<<). Trying to put two variables together with only one << will give you an error message, do not try it. Do not forget to end functions and declarations with a semicolon. If you forget the semicolon, the compiler will give you an error message when you attempt to compile the program.Changing and Comparing VariablesOf course, no matter what type you use, variables are uninteresting without the ability to modify them. Several operators used with variables include the following: *, -, +, /, =, ==, >, <. The * multiplies, the - subtracts, and the + adds. It is of course important to realize that to modify the value of a variable inside the program it is rather important to use the equal sign. In some languages, the equal sign compares the value of the left and right values, but in C++ == is used for that task. The equal sign is still extremely useful. It sets the left input to the equal sign, which must be one, and only one, variable equal to the value on the right side of the equal sign. The operators that perform mathematical functions should be used on the right side of an equal sign in order to assign the result to a variable on the left side.
Here are a few examples:
a = 4 * 6; // (Note use of comments and of semicolon) a is 24
a = a + 5; // a equals the original value of a with five added to it
a == 5 // Does NOT assign five to a. Rather, it checks to see if a equals 5.
The other form of equal, ==, is not a way to assign a value to a variable. Rather, it checks to see if the variables are equal. It is useful in other areas of C++; for example, you will often use == in such constructions as conditional statements and loops. You can probably guess how < and > function. They are greater than and less than operators.
For example:
a < 5 // Checks to see if a is less than five
a > 5 // Checks to see if a is greater than five
a == 5 // Checks to see if a equals five, for good measure
Comparing variables isn't really useful until you have some way of using the results--that's what lesson 2, on if statements is all about.
If you enjoyed this tutorial, check out the Cprogramming.com ebook, Jumping into C++. It contains all the information in this tutorial, plus much much more, in one convenient place, along with tons of sample code and practice problems. Buy Jumping into C++ today!
C++ - Struct
You can have multiple data members of various types in C Language structures. In C++, you can have both data members and function. Actually there is no difference between strcut and class in C++ except all the members declared in struct are public by default whereas in class it is private.
Three access levels are,
1. Private - Can be accessed only by the members of the struct or class
2. Protected - Can be accessed by the struct and its derived struct or class
3. public - Can be accessed by any other struct or class or function.
struct MyClass
{
int m; // By default variables and functions are public
int TestFunc1();
private:
private:
int a;
int b;
public:
MyClass() : a(10), b(20), m(30)
{
};
};
Three access levels are,
1. Private - Can be accessed only by the members of the struct or class
2. Protected - Can be accessed by the struct and its derived struct or class
3. public - Can be accessed by any other struct or class or function.
struct MyClass
{
int m; // By default variables and functions are public
int TestFunc1();
private:
private:
int a;
int b;
public:
MyClass() : a(10), b(20), m(30)
{
};
};
C++ - Class
In C++, class is a keyword. Using class, we can implement all object oriented programming language concepts. All the members declared in C++ classes are private by default. We can also have protected access level to for derived classes and public access level for any functions or classes.
Three access levels are,
1. Private - Can be accessed only by the members of the struct or class
2. Protected - Can be accessed by the struct and its derived struct or class
3. public - Can be accessed by any other struct or class or function.
In C++, class is a keyword. Using class, we can implement all object oriented programming language concepts. All the members declared in C++ classes are private by default. We can also have protected access level to for derived classes and public access level for any functions or classes.Three access levels are,1. Private - Can be accessed only by the members of the struct or class2. Protected - Can be accessed by the struct and its derived struct or class3. public - Can be accessed by any other struct or class or function
class MyString
{
private:
char *m_pString;
public:
MyString()
{
std::cout << "Calling Default Constructor\n";
m_pString = NULL;
}
~MyString()
{
if( this->m_pString != NULL)
{
std::cout << "Calling Destructor\n";
delete this->m_pString;
this->m_pString = NULL;
}
}
MyString(const char *p)
{
std::cout << "Calling Parameterized Constructor\n";
int len = strlen(p);
m_pString = new char [len + 1];
strcpy(m_pString, p);
}
MyString(const MyString &other)
{
std::cout << "Calling Copy Constructor\n";
m_pString = other.m_pString;
//int len = strlen(other.m_pString);
//m_pString = new char [len + 1];
//strcpy(m_pString, other.m_pString);
}
const MyString& operator = (const MyString &other)
{
std::cout << "Calling assignment operator\n";
int len = strlen(other.m_pString);
m_pString = new char [len + 1];
strcpy(m_pString, other.m_pString);
return *this;
}
operator const char*()
{
return this->m_pString;
}
};
Three access levels are,
1. Private - Can be accessed only by the members of the struct or class
2. Protected - Can be accessed by the struct and its derived struct or class
3. public - Can be accessed by any other struct or class or function.
In C++, class is a keyword. Using class, we can implement all object oriented programming language concepts. All the members declared in C++ classes are private by default. We can also have protected access level to for derived classes and public access level for any functions or classes.Three access levels are,1. Private - Can be accessed only by the members of the struct or class2. Protected - Can be accessed by the struct and its derived struct or class3. public - Can be accessed by any other struct or class or function
class MyString
{
private:
char *m_pString;
public:
MyString()
{
std::cout << "Calling Default Constructor\n";
m_pString = NULL;
}
~MyString()
{
if( this->m_pString != NULL)
{
std::cout << "Calling Destructor\n";
delete this->m_pString;
this->m_pString = NULL;
}
}
MyString(const char *p)
{
std::cout << "Calling Parameterized Constructor\n";
int len = strlen(p);
m_pString = new char [len + 1];
strcpy(m_pString, p);
}
MyString(const MyString &other)
{
std::cout << "Calling Copy Constructor\n";
m_pString = other.m_pString;
//int len = strlen(other.m_pString);
//m_pString = new char [len + 1];
//strcpy(m_pString, other.m_pString);
}
const MyString& operator = (const MyString &other)
{
std::cout << "Calling assignment operator\n";
int len = strlen(other.m_pString);
m_pString = new char [len + 1];
strcpy(m_pString, other.m_pString);
return *this;
}
operator const char*()
{
return this->m_pString;
}
};
C++ - Constructor
Constructors are the special type of functions provided in C++ and they will get called at the time of object definition automatically.
MyString is the class name in the given sample code. All constructor functions will use the class name as the function name, only the argument might differ. Based on the arguments we have different types are constructors.
MyString is the class name in the given sample code. All constructor functions will use the class name as the function name, only the argument might differ. Based on the arguments we have different types are constructors.
- Default Constructor - the default constructor is defined in as MyString(), is nothing but the class name with no arguments.
- Copy Constructor - Use the syntax. <classname>(const <classname> &other). Click here to know more about copy constructor
- Parameterized Constructor - These constructors take any other arguments as input other than default and copy constructors. Refer to the syntax MyString(const char *p) in the sample code.
- There is no virtual constructor.
- Constructor can not return any value.
- If you have to return any value from constructor, then use the exceptions.
- Constructors can be called implicitly or explicitly.
- They can be declared private, protected or public to restrict the access level. You can ask one questions - What is the need for declaring constructor as private? Refer to singleton class for more details.
- There can be any number of constructors but only one destructor
C++ - Copy Constructor
Copy Constructor are also the special type of constructors in C++ and they have got a specfic syntax.
The syntax is,
const classname& classname(const classname& other);
There are many ways copy constructors gets called.
1. When the object gets copied explicitly or implicitly
2. When the object gets initialized.
Source Codeclass MyClass
{
private:
int m;
int a;
int b;
public:
MyClass() : a(10), b(20), m(30)
{
};
// Syntax for copy constructor
MyClass(const MyClass &other)
{
this->a = other.a;
this->b = other.b;
this->m = other.m;
}
// Syntax for assignment operator
const MyClass& operator = (const MyClass &other)
{
this->a = other.a;
this->b = other.b;
this->m = other.m;
return *this;
}
};
void main()
{
MyClass a; // calls default constructor
MyClass c; // calls default constructor
MyClass b = a; // calls copy constructor
c = b; // calls assignment operator
}
C++ - Destructor
Destructors are also the special type of functions provided in C++ and they will get called jyst before the object gets deallocated.
Remember that a class can have only one destructor where as they can be many construcors. tMyClass is the class name in the example and the destructor is defined in as ~MyString(), is nothing but the class name.
Remember the following points in Destructors
{
private:
char *m_pString;
public:
MyString()
{
std::cout << "Calling Default Constructor\n";
m_pString = NULL;
}
~MyString()
{
if( this->m_pString != NULL)
{
std::cout << "Calling Destructor\n";
delete this->m_pString;
this->m_pString = NULL;
}
}
MyString(const char *p)
{
std::cout << "Calling Parameterized Constructor\n";
int len = strlen(p);
m_pString = new char [len + 1];
strcpy(m_pString, p);
}
MyString(const MyString &other)
{
std::cout << "Calling Copy Constructor\n";
m_pString = other.m_pString;
//int len = strlen(other.m_pString);
//m_pString = new char [len + 1];
//strcpy(m_pString, other.m_pString);
}
const MyString& operator = (const MyString &other)
{
std::cout << "Calling assignment operator\n";
int len = strlen(other.m_pString);
m_pString = new char [len + 1];
strcpy(m_pString, other.m_pString);
return *this;
}
operator const char*()
{
return this->m_pString;
}
};
Remember that a class can have only one destructor where as they can be many construcors. tMyClass is the class name in the example and the destructor is defined in as ~MyString(), is nothing but the class name.
Remember the following points in Destructors
- There is a virtual destructor. so you can declare destructor as virtual.
- Desstructor can not return any value.
- If you have to return any value from desstructor, then use the exceptions.
- Destructors are usually called automatically at the time of object destruction. There might be very rare cases, you may need to call explicitly, but is not an usual practice.
- Destructor can be declared private, protected or public to restrict the access level. You can ask one questions - What is the need for declaring constructor as private? Refer to singleton class for more details.
- There can be any number of constructors but only one destructor
{
private:
char *m_pString;
public:
MyString()
{
std::cout << "Calling Default Constructor\n";
m_pString = NULL;
}
~MyString()
{
if( this->m_pString != NULL)
{
std::cout << "Calling Destructor\n";
delete this->m_pString;
this->m_pString = NULL;
}
}
MyString(const char *p)
{
std::cout << "Calling Parameterized Constructor\n";
int len = strlen(p);
m_pString = new char [len + 1];
strcpy(m_pString, p);
}
MyString(const MyString &other)
{
std::cout << "Calling Copy Constructor\n";
m_pString = other.m_pString;
//int len = strlen(other.m_pString);
//m_pString = new char [len + 1];
//strcpy(m_pString, other.m_pString);
}
const MyString& operator = (const MyString &other)
{
std::cout << "Calling assignment operator\n";
int len = strlen(other.m_pString);
m_pString = new char [len + 1];
strcpy(m_pString, other.m_pString);
return *this;
}
operator const char*()
{
return this->m_pString;
}
};
C++ - Assignment Operators
The syntax for assignment operator is given below:
The syntax is,
const MyClass& operator = (const MyClass &other)
There are two ways assignment operators gets called.
1. When the object gets assigned implicitly
2. When the object gets assigned explicitly.
Source Codeclass MyClass
{
private:
int m;
int a;
int b;
public:
MyClass() : a(10), b(20), m(30)
{
};
// Syntax for copy constructor
MyClass(const MyClass &other)
{
this->a = other.a;
this->b = other.b;
this->m = other.m;
}
// Syntax for assignment operator
const MyClass& operator = (const MyClass &other)
{
this->a = other.a;
this->b = other.b;
this->m = other.m;
return *this;
}
};
void main()
{
MyClass a; // calls default constructor
MyClass c; // calls default constructor
MyClass b = a; // calls copy constructor
c = b; // calls assignment operator
}
The syntax is,
const MyClass& operator = (const MyClass &other)
There are two ways assignment operators gets called.
1. When the object gets assigned implicitly
2. When the object gets assigned explicitly.
Source Codeclass MyClass
{
private:
int m;
int a;
int b;
public:
MyClass() : a(10), b(20), m(30)
{
};
// Syntax for copy constructor
MyClass(const MyClass &other)
{
this->a = other.a;
this->b = other.b;
this->m = other.m;
}
// Syntax for assignment operator
const MyClass& operator = (const MyClass &other)
{
this->a = other.a;
this->b = other.b;
this->m = other.m;
return *this;
}
};
void main()
{
MyClass a; // calls default constructor
MyClass c; // calls default constructor
MyClass b = a; // calls copy constructor
c = b; // calls assignment operator
}
C++ - Operator Overloading
Here is the sample code for operator overloading.
I have overloaded the following three operators for the class MyValueClass.
1. operator = (assignment)
2. operator += (plus equal to)
3. operator + (plus)
I have overloaded assignment operator and operator += in the begining. You can see two implementation for binary arithmatic operator +. One with using the existing += operator and another one with out using += operator.
Source Codeclass MyValueClass {
public:
int a;
int b;
public:
MyValueClass() { };
MyValueClass(int v1, int v2) : a(v1), b(v2) { };
MyValueClass(const MyValueClass& other)
{
this->a = other.a;
this->b = other.b;
}
const MyValueClass& operator = (const MyValueClass& other)
{
this->a = other.a;
this->b = other.b;
return *this;
}
MyValueClass& operator += (const MyValueClass& other)
{
this->a += other.a;
this->b += other.b;
return *this;
}
const MyValueClass operator + (const MyValueClass& other) const
{
MyValueClass m;
m.a = this->a + other.a;
m.b = this->b + other.b;
return m;
}
/*
// This is an alternate implementation for operator + using the operator +=
const MyValueClass operator + (const MyValueClass& other) const
{
MyValueClass m = *this;
m += other; // calling operator += , same as m.operator += (other);
return m;
}
*/
};
void main()
{
MyValueClass Obj1(5,10);
MyValueClass Obj2(15,20);
MyValueClass Obj3(25,30);
MyValueClass Obj4 = Obj1 + Obj2 + Obj3;
Obj2 += Obj3;
std::cout << "The value of Obj4 = " << Obj4.a << ", " << Obj4.b << "\n";
std::cout << "The value of Obj2 = " << Obj2.a << ", " << Obj2.b << "\n";
}
OutputThe value of Obj4 = 45, 60
The value of Obj5 = 40, 50
I have overloaded the following three operators for the class MyValueClass.
1. operator = (assignment)
2. operator += (plus equal to)
3. operator + (plus)
I have overloaded assignment operator and operator += in the begining. You can see two implementation for binary arithmatic operator +. One with using the existing += operator and another one with out using += operator.
Source Codeclass MyValueClass {
public:
int a;
int b;
public:
MyValueClass() { };
MyValueClass(int v1, int v2) : a(v1), b(v2) { };
MyValueClass(const MyValueClass& other)
{
this->a = other.a;
this->b = other.b;
}
const MyValueClass& operator = (const MyValueClass& other)
{
this->a = other.a;
this->b = other.b;
return *this;
}
MyValueClass& operator += (const MyValueClass& other)
{
this->a += other.a;
this->b += other.b;
return *this;
}
const MyValueClass operator + (const MyValueClass& other) const
{
MyValueClass m;
m.a = this->a + other.a;
m.b = this->b + other.b;
return m;
}
/*
// This is an alternate implementation for operator + using the operator +=
const MyValueClass operator + (const MyValueClass& other) const
{
MyValueClass m = *this;
m += other; // calling operator += , same as m.operator += (other);
return m;
}
*/
};
void main()
{
MyValueClass Obj1(5,10);
MyValueClass Obj2(15,20);
MyValueClass Obj3(25,30);
MyValueClass Obj4 = Obj1 + Obj2 + Obj3;
Obj2 += Obj3;
std::cout << "The value of Obj4 = " << Obj4.a << ", " << Obj4.b << "\n";
std::cout << "The value of Obj2 = " << Obj2.a << ", " << Obj2.b << "\n";
}
OutputThe value of Obj4 = 45, 60
The value of Obj5 = 40, 50
C++ - Preincrement and Postincrement operator overloading
We can overload both preincrement and postincrement operators in C++. We need to pass a dummy argument int to specify that it is post increment. The same logic applies to pre decrement and post decrement operators also.
Here is the sample code:
class MyIncrDecrClass
{
public:
int m_nCounter;
public:
MyIncrDecrClass() : m_nCounter(0)
{
}
// The following operator++() represents overloading of pre-increment
MyIncrDecrClass& operator++()
{
++this->m_nCounter;
return *this;
}
// Passing dummy int argument is to mention overloading of post-increment
MyIncrDecrClass& operator++(int)
{
this->m_nCounter++;
return *this;
}
// The following operator--() represents overloading of pre-decrement
MyIncrDecrClass& operator--()
{
--this->m_nCounter;
return *this;
}
// Passing dummy int argument is to mention overloading of post-decrement
MyIncrDecrClass& operator--(int)
{
this->m_nCounter--;
return *this;
}
};
void main()
{
MyIncrDecrClass counter;
counter++; // calls post increment operator function
++counter; // calls pre increment operator function
counter--; // calls post decrement operator function
--counter; // calls pre decrement operator function
}
Here is the sample code:
class MyIncrDecrClass
{
public:
int m_nCounter;
public:
MyIncrDecrClass() : m_nCounter(0)
{
}
// The following operator++() represents overloading of pre-increment
MyIncrDecrClass& operator++()
{
++this->m_nCounter;
return *this;
}
// Passing dummy int argument is to mention overloading of post-increment
MyIncrDecrClass& operator++(int)
{
this->m_nCounter++;
return *this;
}
// The following operator--() represents overloading of pre-decrement
MyIncrDecrClass& operator--()
{
--this->m_nCounter;
return *this;
}
// Passing dummy int argument is to mention overloading of post-decrement
MyIncrDecrClass& operator--(int)
{
this->m_nCounter--;
return *this;
}
};
void main()
{
MyIncrDecrClass counter;
counter++; // calls post increment operator function
++counter; // calls pre increment operator function
counter--; // calls post decrement operator function
--counter; // calls pre decrement operator function
}
C++ - Inheritance
Inheritance means classes can be derived from another class called base class. Derived classes will have all the features of the base class and it will have access to base class protected and public members. Derived classes will not have access to private members of the base class.
We know C++, C# and Java supportes inheritance. But there are differences in the inheritance implementation between C++, C# and Java Inheritance. In C++, you need to use the virutal keyword in both base and derived classes. In C#, you need to use virual keyword in base case and override keyword in derived classes.
In Java you do not need to use any keyword like virtual or override since by default all non static functions are considered as virual. You have to make it either private or use final keyword to remove the default virtual feature in each function in the Java classes.
In this sample, Shape is the base class. Triangle and Circle are the derived classes derived from the base class Shape. It is called inheritance.
We know C++, C# and Java supportes inheritance. But there are differences in the inheritance implementation between C++, C# and Java Inheritance. In C++, you need to use the virutal keyword in both base and derived classes. In C#, you need to use virual keyword in base case and override keyword in derived classes.
In Java you do not need to use any keyword like virtual or override since by default all non static functions are considered as virual. You have to make it either private or use final keyword to remove the default virtual feature in each function in the Java classes.
In this sample, Shape is the base class. Triangle and Circle are the derived classes derived from the base class Shape. It is called inheritance.
C++ - Multiple Inheritance
In this sample, Shape is the base class. Triangle and Circle are the derived classes derived from the base class Shape. It is called inheritance.
class Cone is derived from both two base classes Triangle and Circle. It is called Multiple Inheritance.
Source Codeclass Shape
{
public:
Shape()
{
std::cout << "Shape\n";
}
virtual void draw() { };
virtual void display() { };
};
class Circle : public Shape
{
int r;
public:
Circle()
{
std::cout << "Circle\n\n";
}
virtual void draw() {};
virtual void display() { };
};
class Triangle : public Shape
{
int a,b,c;
public:
Triangle()
{
std::cout << "Triangle\n\n";
}
virtual void draw() {};
virtual void display() { };
};
class Cone : public Triangle, public Circle
{
public:
Cone()
{
std::cout << "Cone\n\n";
}
virtual void draw() {};
virtual void display() { };
};
C++ - Virtual Functions
virtual functions are the functions can be overridden by the derived classes by changing its default behavior. I have explained how the concept of virtual function works in derived classes with example.
By including one or more virtual functions will increase the size of the class by 4 bytes. This 4 bytes are used to store the address of the array of function pointers. In the following sample code, we have got two virtual functions.
In the main function, we have got 4 Shape* objects p0, p1, p2 and p3 and all objects are calling its corresponding derived class draw function. Lets check the function pointer table on debugger for all the 4 objects. The following are the screenshots for all 4 objects.
By including one or more virtual functions will increase the size of the class by 4 bytes. This 4 bytes are used to store the address of the array of function pointers. In the following sample code, we have got two virtual functions.
In the main function, we have got 4 Shape* objects p0, p1, p2 and p3 and all objects are calling its corresponding derived class draw function. Lets check the function pointer table on debugger for all the 4 objects. The following are the screenshots for all 4 objects.
Even if p0, p1, p2 and p3 are the pointers to Shape object, their address pointing to array of virtual function table are different. From the screen shot given above, we can see that the different function addresses are used when we make a call to draw function from the base class pointer object.
0x004111a9 Shape::draw function
0x0041103c Rect1::draw function
0x0041100a Circle::draw function
0x00411293 Square::draw function
Source Code#include <iostream>
#include <tchar.h>
class Shape
{
public:
Shape()
{
std::cout << "Shape\n";
}
virtual void draw() { }
virtual void display() { }
};
class Rect1 : public Shape
{
int l,b;
public:
Rect1()
{
std::cout << "Rectangle\n\n";
}
virtual void draw() {}
virtual void display() { }
};
class Circle : public Shape
{
int r;
public:
Circle()
{
std::cout << "Circle\n\n";
}
virtual void draw() {}
virtual void display() { }
};
class Square : public Shape
{
int a;
public:
Square()
{
std::cout << "Square\n\n";
}
virtual void draw() {}
virtual void display() { }
};
int _tmain(int argc, _TCHAR* argv[])
{
Shape *p0 = new Shape();
Shape *p1 = static_cast<Shape*> (new Rect1());
Shape *p2 = static_cast<Shape*> (new Circle());
Shape *p3 = static_cast<Shape*> (new Square());
p0->draw(); // calls Shape::draw() function
p1->draw(); // calls Rect1::draw() function
p2->draw(); // calls Circle::draw() function
p3->draw(); // calls Square::draw() function
return 0;
}
OutputShape
Shape
Rectangle
Shape
Circle
Shape
Square
0x004111a9 Shape::draw function
0x0041103c Rect1::draw function
0x0041100a Circle::draw function
0x00411293 Square::draw function
Source Code#include <iostream>
#include <tchar.h>
class Shape
{
public:
Shape()
{
std::cout << "Shape\n";
}
virtual void draw() { }
virtual void display() { }
};
class Rect1 : public Shape
{
int l,b;
public:
Rect1()
{
std::cout << "Rectangle\n\n";
}
virtual void draw() {}
virtual void display() { }
};
class Circle : public Shape
{
int r;
public:
Circle()
{
std::cout << "Circle\n\n";
}
virtual void draw() {}
virtual void display() { }
};
class Square : public Shape
{
int a;
public:
Square()
{
std::cout << "Square\n\n";
}
virtual void draw() {}
virtual void display() { }
};
int _tmain(int argc, _TCHAR* argv[])
{
Shape *p0 = new Shape();
Shape *p1 = static_cast<Shape*> (new Rect1());
Shape *p2 = static_cast<Shape*> (new Circle());
Shape *p3 = static_cast<Shape*> (new Square());
p0->draw(); // calls Shape::draw() function
p1->draw(); // calls Rect1::draw() function
p2->draw(); // calls Circle::draw() function
p3->draw(); // calls Square::draw() function
return 0;
}
OutputShape
Shape
Rectangle
Shape
Circle
Shape
Square
C++ - Abstract Class
A class with at least one pure virtual function is called abstract class. We can not instantiate an abstract class.
A pure virtual function is nothing but no implementation and assigned with 0. For example: virtual void draw() = 0; You can not instantiate the Shape class in the given example. In order to instantiate, you must override this function with a derived class. In the sample code given below, Circle is a dervied class dervied from the class Shape.
Source Code
class Shape
{
protected:
virtual void draw() = 0; // pure virtual function
}
class Circle : public Shape
{
int r;
public:
Circle()
{
std::cout << "Circle\n\n";
}
virtual void draw() {}
virtual void display() { }
};
void main()
{
Shape s; // error C2259: 'Shape' : cannot instantiate abstract class due to following members: 'void Shape::draw(void)' : is abstract
}
A pure virtual function is nothing but no implementation and assigned with 0. For example: virtual void draw() = 0; You can not instantiate the Shape class in the given example. In order to instantiate, you must override this function with a derived class. In the sample code given below, Circle is a dervied class dervied from the class Shape.
Source Code
class Shape
{
protected:
virtual void draw() = 0; // pure virtual function
}
class Circle : public Shape
{
int r;
public:
Circle()
{
std::cout << "Circle\n\n";
}
virtual void draw() {}
virtual void display() { }
};
void main()
{
Shape s; // error C2259: 'Shape' : cannot instantiate abstract class due to following members: 'void Shape::draw(void)' : is abstract
}
C++ - Abstraction
Abstraction is an important concept in C++. If you are developing the class library that can be used by N number of peoples, then you may not want to expose all the properties and implementation details of the class. Exposing the methods what is mandatory and hiding the rest.
Here is one example for abstraction which can take input and produces the result. The purpose of this class this finding the standard deviation for the given series and nothing else. Do not argue here that we must expose mean and variance as this is also an useful feature as a part of class implementation.
If we need an abstraction concept explained in C++ code that compiles and gives the output, then I have to take the complex real time example. Otherwise I have to take an example that can not expressed and written in C++ like how a car driver does not to know how the engine and internal part works.
I have written a class call StdDeviation and it exposes only two methods SetValues() and GetStandardDeviation(). It hides the implementation for how standard deviation is calculated. The implementation details here are calculating the mean and variance and they are not exposed to the user.
Source Code#include <stdio.h>
#include <iostream>
#include <tchar.h>
#include <math.h>
class StdDeviation
{
private:
int max;
int value[100];
double mean;
double CalculateMean()
{
double sum = 0;
for(int i = 0; i < max; i++)
sum += value[i];
return (sum / max);
}
double CalculateVariane()
{
mean = CalculateMean();
double temp = 0;
for(int i = 0; i < max; i++)
{
temp += (value[i] - mean) * (value[i] - mean) ;
}
return temp / max;
}
public:
int SetValues(int *p, int count)
{
if(count > 100)
return -1;
max = count;
for(int i = 0; i < count; i++)
value[i] = p[i];
return 0;
}
double GetStandardDeviation()
{
return sqrt(CalculateVariane());
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int arrSeries[] = { 10, 20, 20, 30, 30, 30, 40, 50 };
StdDeviation sd;
sd.SetValues(arrSeries, sizeof(arrSeries) / sizeof(arrSeries[0]));
double v = sd.GetStandardDeviation();
std::cout << "Population Standard Deviation is: " << v << "\n\n";
}
OutputPopulation Standard Deviation is: 11.6592
C++ - Polymorphism
If there are multiple classes (rectangle, circle) derived from common base class (shape), polymorphism provides the ability to call the methods in derived classes (rectangle, circle) using the base class (shape) pointers.
To understand the poymorphism, you need to know about the virtual functions and inheritance. Inheritance means classes can be derived from another class called base class. Derived classes will have all the features of the base class and it will have access to base class protected and public members. Derived classes will not have access to private members of the base class.
Regarding Virtual Functions - In C++, you need to use the virutal keyword in both base and derived classes. In C#, you need to use virual keyword in base case and override keyword in derived classes. In Java you do not need to use any keyword like virtual or override since by default all non static functions are considered as virual. You have to make it either private or use final keyword to remove the default virtual feature in each function in the Java classes.
There are four classes given on this example. Shape is a base class and Rect1, Circle and Triangle are the classes derived from the base class Shape. The base class Shape* is used to access all three dervied class functions. It is called Polymorphism.
C++ - Data Hiding
Data Hiding is a concept in C++. In C Language Struct can not hide data of its data members. Where as in C++, we got the luxary of hiding data using e different access levels - private, protected, public
Private members and functions can only be accessed by class members of the class. You can think the data abstraction is also using data hiding techniques. Protected members can be accessed only by the class and its derived classes. Note: By using friend keyword, functions and classes will get access to the private and protected members of the classes.
class CStudent
{
private:
char name[128];
int age;
char addr1[128];
char addr2[128];
char city[32];
char zipcode[10];
public:
CStudent() {}
~CStudent() {}
const char* GetName() const { return name; }
const char* GetAddr1() const { return addr1; }
const char* GetAddr2() const { return addr2; }
const char* GetCity() const { return city; }
const char* GetZipCode() const { return zipcode; }
int GetAge() const { return age; }
void SetName(const char* p) { strcpy(name, p); }
void SetAddr1(const char* p) { strcpy(addr1, p); }
void SetAddr2(const char* p) { strcpy(addr2, p); }
void SetCity(const char* p) { strcpy(city, p); }
void SetZipCode(const char* p) { strcpy(zipcode, p); }
void GetAge(int v) { age = v; }
};
C++ - Encapsulation
When we have a class CStudent defined in the given example below, the programmers can not access the member variables directly. They need to go through the Get and Set functions. This explains the concepts of encapsulation. It also explains the concept of data hiding. Using private keyword, the data and methods of the functions can be hidden or can be accessible only by the class members. We can extend the access level to derived classes by using protected keyword.
Sample Code
class CStudent
{
private:
char name[128];
int age;
char addr1[128];
char addr2[128];
char city[32];
char zipcode[10];
public:
CStudent() {}
~CStudent() {}
const char* GetName() const { return name; }
const char* GetAddr1() const { return addr1; }
const char* GetAddr2() const { return addr2; }
const char* GetCity() const { return city; }
const char* GetZipCode() const { return zipcode; }
int GetAge() const { return age; }
void SetName(const char* p) { strcpy(name, p); }
void SetAddr1(const char* p) { strcpy(addr1, p); }
void SetAddr2(const char* p) { strcpy(addr2, p); }
void SetCity(const char* p) { strcpy(city, p); }
void SetZipCode(const char* p) { strcpy(zipcode, p); }
void GetAge(int v) { age = v; }
};
Sample Code
class CStudent
{
private:
char name[128];
int age;
char addr1[128];
char addr2[128];
char city[32];
char zipcode[10];
public:
CStudent() {}
~CStudent() {}
const char* GetName() const { return name; }
const char* GetAddr1() const { return addr1; }
const char* GetAddr2() const { return addr2; }
const char* GetCity() const { return city; }
const char* GetZipCode() const { return zipcode; }
int GetAge() const { return age; }
void SetName(const char* p) { strcpy(name, p); }
void SetAddr1(const char* p) { strcpy(addr1, p); }
void SetAddr2(const char* p) { strcpy(addr2, p); }
void SetCity(const char* p) { strcpy(city, p); }
void SetZipCode(const char* p) { strcpy(zipcode, p); }
void GetAge(int v) { age = v; }
};
C++ - Difference Between Pointers and References
Pointers can be NULL whereas reference can not.
References must be initalized unlike pointers.
Reference variable in a class must be initialized via C++ initializer list in the constructor.
If we need a optional argument in function, we can use pointer otherwise reference.
class MyRefClass
{
private:
int &a;
int &b;
MyRefClass();
public:
// Ignoring the initialization will give an compile time error error C2758: 'MyRefClass::b' : must be initialized in constructor base/member initializer list
MyRefClass(int arg1, int arg2) : a(arg1), b(arg2)
{
}
};
References must be initalized unlike pointers.
Reference variable in a class must be initialized via C++ initializer list in the constructor.
If we need a optional argument in function, we can use pointer otherwise reference.
class MyRefClass
{
private:
int &a;
int &b;
MyRefClass();
public:
// Ignoring the initialization will give an compile time error error C2758: 'MyRefClass::b' : must be initialized in constructor base/member initializer list
MyRefClass(int arg1, int arg2) : a(arg1), b(arg2)
{
}
};
C++ - Function Pointers
The following is the sample declaration for function pointer that takes two integers as input and returns an integer value.
int (*fp1)(int, int);
The following is the sample declaration for a function that takes function pointer as an argument.
int PassFuncPtr(int (*fp)(int, int));
The following is the definition of the above function declaration. It simply calls the function with the hard coded values of 10 and 20.
Source Codeint PassFuncPtr(int (*fp)(int, int))
{
return fp(10, 20);
}
int addition(int a, int b)
{
return a+b;
}
int _tmain(int argc, _TCHAR* argv[])
{
int (*fp1)(int, int);
fp1 = addition;
int value = PassFuncPtr(addition); // we can also pass fp1 here
std::cout << value;
}
Output30
int (*fp1)(int, int);
The following is the sample declaration for a function that takes function pointer as an argument.
int PassFuncPtr(int (*fp)(int, int));
The following is the definition of the above function declaration. It simply calls the function with the hard coded values of 10 and 20.
Source Codeint PassFuncPtr(int (*fp)(int, int))
{
return fp(10, 20);
}
int addition(int a, int b)
{
return a+b;
}
int _tmain(int argc, _TCHAR* argv[])
{
int (*fp1)(int, int);
fp1 = addition;
int value = PassFuncPtr(addition); // we can also pass fp1 here
std::cout << value;
}
Output30
C++ - Function Templates
A function template can be used when it does the work based on the generic data types. It is often used to write an algorithms when the program flow would be sample but the data type differs on case to case.
A sample function template is given below as you see it does the simple addition on generic data type called class which will defined later. When we start using this template function, then compiler will generate a function with actual data types. In case, we are using this function on 3 different data types, then we will have 3 different sets of function at run time. At run time, there will not be any code call "template". All templates will be replaced with actual arguments during compile time itself.
Many class libraries and algorithms are developed using templates. It provides the operation on generic data type. Using templates will not increase or decrease at run time. Code maintenance will be easier by using templates.
In the following example, we will have two sets of add functions generated by compiler one for int and the other for double. In case, we are not using this template function, then compiler will not generate even one function.
Source Codetemplate
T add(T x, T y)
{
return x + y;
}
int _tmain(int argc, _TCHAR* argv[])
{
int c1 = add((int)sz1, (int)sz2);
double c2 = add((double)sz1, (double)sz2);
int (*fp1)(int, int);
double (*fp2)(double, double);
fp1 = add;
fp2 = add;
int c3 = fp1((int)sz1, (int)sz2);
int c4 = fp2((double)sz1, (double)sz2);
}
Output
None
C++ - Class Templates
Likewise function, we can use templates in classes also. I have written a class MySocket which is derived from a templatized class. MySocket will accept the CHTTPImpl class as a default argument for template class name. I have written another base class called CSecureHTTPImpl, this can also be passed as an argument for template class MySocket. Look at the main function code for the usage.
In Standard Template Library(STL) is effectively used in C++ and it is a very good example for template. It has got both function and class templates. Another example would be Active Template Library(ATL) which is widely used in COM technologies.
Source Codeclass CHTTPImpl
{
private:
int m_port;
std::string m_hostname;
public:
CHTTPImpl() : m_port(80) { }
void SendMessage()
{
std::cout << "SendMessage from Http Protocol\n";
}
void RecvMessage()
{
std::cout << "RecvMessage from Http Protocol\n";
}
};
class CSecureHTTPImpl
{
private:
int m_port;
std::string m_hostname;
public:
CSecureHTTPImpl() : m_port(443) { }
void SendMessage()
{
std::cout << "SendMessage from Secure Http Protocol\n";
}
void RecvMessage()
{
std::cout << "RecvMessage from Secure Http Protocol\n";
}
};
template<class TSockImpl = CHTTPImpl>
class MySocket : public TSockImpl
{
public:
void SendMessage() { TSockImpl::SendMessage(); }
void RecvMessage() { TSockImpl::RecvMessage(); }
};
int _tmain(int argc, _TCHAR* argv[])
{
MySocket<> m;
m.SendMessage();
m.RecvMessage();
MySocket<CSecureHttpImpl> sm;
sm.SendMessage();
sm.RecvMessage();
return 0;
}
OutputSendMessage from Http Protocol
RecvMessage from Http Protocol
SendMessage from Secure Http Protocol
RecvMessage from Secure Http Protocol
C++ - Singleton Class
If there is a need to create only one instance of a class, then make sure,
1. Default and Copy constructors are declared as private.
2. Assignment operator is declared as private.
3. Have a static function that will return the pointer to the class.
Source Code#include <iostream>
class MySingletonClass {
private:
int m_nValue;
MySingletonClass() { };
MySingletonClass(const MySingletonClass& other);
const MySingletonClass& operator = (const MySingletonClass& other);
public:
static MySingletonClass* m_pMySingletonClass;
static MySingletonClass* GetInstance()
{
if(m_pMySingletonClass == NULL)
m_pMySingletonClass = new MySingletonClass();
return m_pMySingletonClass;
}
int GetValue() const { return m_nValue; }
void SetValue(int nVal) { m_nValue = nVal; }
};
MySingletonClass* MySingletonClass::m_pMySingletonClass = NULL;
int main()
{
MySingletonClass *p1 = MySingletonClass::GetInstance();
MySingletonClass *p2 = MySingletonClass::GetInstance();
// Both instances will point to the same object
p1->SetValue(100);
std::cout << p2->GetValue();
}
Output
100
1. Default and Copy constructors are declared as private.
2. Assignment operator is declared as private.
3. Have a static function that will return the pointer to the class.
Source Code#include <iostream>
class MySingletonClass {
private:
int m_nValue;
MySingletonClass() { };
MySingletonClass(const MySingletonClass& other);
const MySingletonClass& operator = (const MySingletonClass& other);
public:
static MySingletonClass* m_pMySingletonClass;
static MySingletonClass* GetInstance()
{
if(m_pMySingletonClass == NULL)
m_pMySingletonClass = new MySingletonClass();
return m_pMySingletonClass;
}
int GetValue() const { return m_nValue; }
void SetValue(int nVal) { m_nValue = nVal; }
};
MySingletonClass* MySingletonClass::m_pMySingletonClass = NULL;
int main()
{
MySingletonClass *p1 = MySingletonClass::GetInstance();
MySingletonClass *p2 = MySingletonClass::GetInstance();
// Both instances will point to the same object
p1->SetValue(100);
std::cout << p2->GetValue();
}
Output
100
C++ - Exceptions and Stack Unwinding Process
Exceptions (try, throw, catch) are very useful in C++. With in the catch block, we can either write the log message or let the user knows about what went wrong. Sometimes it can be used to come out of the nested for loops for 3 to 4 levels.
When throwing an exception with in a try block, program control then directly goes to the corresponding catch block or default catch(...) by doing the stack unwinding.
Stack unwinding is the very good feature in C++. During this process all the destructors are called in the reverss order.
Source Code#include <iostream>
class CConfig
{
std::string m_name;
public:
CConfig()
{
m_name = "";
}
CConfig(const char *name)
{
this->m_name = name;
}
CConfig(const CConfig &other)
{
this->m_name = other.m_name;
}
const CConfig& operator = (const CConfig &other)
{
this->m_name = other.m_name;
return *this;
}
void CalculateError()
{
std::cout << "Exception Occurs\n";
throw -1; // just throw an exception
}
};
class MyObjectONE
{
public:
MyObjectONE() { }
~MyObjectONE()
{
std::cout << "Calling destructor of MyObejectOne\n";
}
};
class MyObjectTWO
{
public:
MyObjectTWO() { }
~MyObjectTWO()
{
std::cout << "Calling destructor of MyObjectTWO\n";
}
};
class MyObjectTHREE
{
public:
MyObjectTHREE() { }
~MyObjectTHREE()
{
std::cout << "Calling destructor of MyObjectTHREE\n";
}
};
void TestException(CConfig &config)
{
config.CalculateError(); // Throws an exception
}
void TestFunc()
{
std::cout << "TestFunc Begins\n";
CConfig theConfig("MyApp");
MyObjectONE one;
MyObjectTWO two;
MyObjectTHREE three;
TestException(theConfig);
// The remaining lines will not get executed because of throwing exception in TextException
std::cout << "TestFunc Ends\n";
}
int main()
{
try
{
for(int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
for(int k = 0; k < 10; k++)
{
TestFunc();
}
}
}
}
catch(...)
{
}
return 0;
}
OutputTestFunc Begins
Exception Occurs
Calling destructor of MyObjectTHREE
Calling destructor of MyObjectTWO
Calling destructor of MyObejectOne
When throwing an exception with in a try block, program control then directly goes to the corresponding catch block or default catch(...) by doing the stack unwinding.
Stack unwinding is the very good feature in C++. During this process all the destructors are called in the reverss order.
Source Code#include <iostream>
class CConfig
{
std::string m_name;
public:
CConfig()
{
m_name = "";
}
CConfig(const char *name)
{
this->m_name = name;
}
CConfig(const CConfig &other)
{
this->m_name = other.m_name;
}
const CConfig& operator = (const CConfig &other)
{
this->m_name = other.m_name;
return *this;
}
void CalculateError()
{
std::cout << "Exception Occurs\n";
throw -1; // just throw an exception
}
};
class MyObjectONE
{
public:
MyObjectONE() { }
~MyObjectONE()
{
std::cout << "Calling destructor of MyObejectOne\n";
}
};
class MyObjectTWO
{
public:
MyObjectTWO() { }
~MyObjectTWO()
{
std::cout << "Calling destructor of MyObjectTWO\n";
}
};
class MyObjectTHREE
{
public:
MyObjectTHREE() { }
~MyObjectTHREE()
{
std::cout << "Calling destructor of MyObjectTHREE\n";
}
};
void TestException(CConfig &config)
{
config.CalculateError(); // Throws an exception
}
void TestFunc()
{
std::cout << "TestFunc Begins\n";
CConfig theConfig("MyApp");
MyObjectONE one;
MyObjectTWO two;
MyObjectTHREE three;
TestException(theConfig);
// The remaining lines will not get executed because of throwing exception in TextException
std::cout << "TestFunc Ends\n";
}
int main()
{
try
{
for(int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
for(int k = 0; k < 10; k++)
{
TestFunc();
}
}
}
}
catch(...)
{
}
return 0;
}
OutputTestFunc Begins
Exception Occurs
Calling destructor of MyObjectTHREE
Calling destructor of MyObjectTWO
Calling destructor of MyObejectOne
C++ - Shallow and Deep Copy
Shallow copy is used when there are no pointers variable. Deep copy is used when there is a pointer variable. Note we can use shallow copy, if we are using smart pointers which has got referece count. Smart Pointers are efficient way for memory management.
When there is a pointer member variable, just assigning the pointer variable from one class member to another class member is called shallow copy. So the pointer member variable in both classes will point to the same memory location.
When there is a pointer variable, just assigning the pointer variable from one class member to another class member is called shallow copy.
In the following sample code, I have used deep copy in assignment operator and shallow copy in copy constructor. When we use copy constructor in main function for the object str2, the program crashes at the time of exit as we have used shallow copy for pointer object, both objects str1.pMyString and str2.pMyString will point to the same location.
MyString str1("Welcome");
MyString str2 = str1; // calling copy constructor using shallow copy
When use assignment operator for the object str2, the program would work fine.
MyString str1("Welcome");
MyString str2;
str2 = str1; // calling assignment operator using deep copy
The correct implementation would be using deep copy for copy constructor.
Source Codeclass MyString
{
private:
char *m_pString;
public:
MyString()
{
std::cout << "Calling Default Constructor\n";
m_pString = NULL;
}
~MyString()
{
if( this->m_pString != NULL)
{
std::cout << "Calling Destructor\n"; delete this->m_pString;
this->m_pString = NULL;
}
}
MyString(const char *p)
{
std::cout << "Calling Parameterized Constructor\n";
int len = strlen(p);
m_pString = new char [len + 1];
strcpy(m_pString, p);
}
MyString(const MyString &other)
{
std::cout << "Calling Copy Constructor\n";
m_pString = other.m_pString;
//The following lines are for deep copy implementation
//int len = strlen(other.m_pString);
//m_pString = new char [len + 1];
//strcpy(m_pString, other.m_pString);
}
const MyString& operator = (const MyString &other)
{
std::cout << "Calling assignment operator\n";
int len = strlen(other.m_pString);
m_pString = new char [len + 1];
strcpy(m_pString, other.m_pString);
return *this;
}
operator const char*()
{
return this->m_pString;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyString str1("Welcome");
MyString str2 = str1; // calling copy constructor using shallow copy
//MyString str2;
//str2 = str1; // calling assignment operator using deep copy
return 0;
}
OutputCalling Parameterized Constructor
Calling Copy Constructor
When there is a pointer member variable, just assigning the pointer variable from one class member to another class member is called shallow copy. So the pointer member variable in both classes will point to the same memory location.
When there is a pointer variable, just assigning the pointer variable from one class member to another class member is called shallow copy.
In the following sample code, I have used deep copy in assignment operator and shallow copy in copy constructor. When we use copy constructor in main function for the object str2, the program crashes at the time of exit as we have used shallow copy for pointer object, both objects str1.pMyString and str2.pMyString will point to the same location.
MyString str1("Welcome");
MyString str2 = str1; // calling copy constructor using shallow copy
When use assignment operator for the object str2, the program would work fine.
MyString str1("Welcome");
MyString str2;
str2 = str1; // calling assignment operator using deep copy
The correct implementation would be using deep copy for copy constructor.
Source Codeclass MyString
{
private:
char *m_pString;
public:
MyString()
{
std::cout << "Calling Default Constructor\n";
m_pString = NULL;
}
~MyString()
{
if( this->m_pString != NULL)
{
std::cout << "Calling Destructor\n"; delete this->m_pString;
this->m_pString = NULL;
}
}
MyString(const char *p)
{
std::cout << "Calling Parameterized Constructor\n";
int len = strlen(p);
m_pString = new char [len + 1];
strcpy(m_pString, p);
}
MyString(const MyString &other)
{
std::cout << "Calling Copy Constructor\n";
m_pString = other.m_pString;
//The following lines are for deep copy implementation
//int len = strlen(other.m_pString);
//m_pString = new char [len + 1];
//strcpy(m_pString, other.m_pString);
}
const MyString& operator = (const MyString &other)
{
std::cout << "Calling assignment operator\n";
int len = strlen(other.m_pString);
m_pString = new char [len + 1];
strcpy(m_pString, other.m_pString);
return *this;
}
operator const char*()
{
return this->m_pString;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyString str1("Welcome");
MyString str2 = str1; // calling copy constructor using shallow copy
//MyString str2;
//str2 = str1; // calling assignment operator using deep copy
return 0;
}
OutputCalling Parameterized Constructor
Calling Copy Constructor
C++ - Mutable Will Never be Constant
Mutuable is a keyword used in a class for a member variable and that variable will never be constant and can changed even with in a const function.
class MyClass
{
private:
mutable int m;
int a;
int b;
public:
void func1() const
{
// a = 10; Error: l-value specifies const object
// b = 20; Error: l-value specifies const object
m = 30;
}
int getA() const
{
return a;
}
};
class MyClass
{
private:
mutable int m;
int a;
int b;
public:
void func1() const
{
// a = 10; Error: l-value specifies const object
// b = 20; Error: l-value specifies const object
m = 30;
}
int getA() const
{
return a;
}
};
C++ - Pragma Pack Macro
Using pragma pack macro is good for storage, however it may need more Memory IO read and write cycle.
#pragma pack(1)
struct MyStruct1
{
int a; // allocates 4 bytes
char ch1; // allocates 1 byte
int b; // allocates 4 bytes
char ch2; // allocates 1 byte
};
In the above example, to read the value of b, we need two IO read cycles in 32 bit machine because of its memory alignment.
cout << sizeof(MyStruct1); // displays 10
#pragma pack(2)
struct MyStruct2
{
int a; // allocates 4 bytes
char ch1; // allocates 2 byte
int b; // allocates 4 bytes
char ch2; // allocates 2 byte
};
cout << sizeof(MyStruct2); // displays 12
#pragma pack(4)
struct MyStruct3
{
int a; // allocates 4 bytes
char ch1; // allocates 4 byte
int b; // allocates 4 bytes
char ch2; // allocates 4 byte
};
cout << sizeof(MyStruct3); // displays 16 In the above example, to read the value of b, we need only one IO read cycles in 32 bit machine because of its memory alignment.
#pragma pack(1)
struct MyStruct1
{
int a; // allocates 4 bytes
char ch1; // allocates 1 byte
int b; // allocates 4 bytes
char ch2; // allocates 1 byte
};
In the above example, to read the value of b, we need two IO read cycles in 32 bit machine because of its memory alignment.
cout << sizeof(MyStruct1); // displays 10
#pragma pack(2)
struct MyStruct2
{
int a; // allocates 4 bytes
char ch1; // allocates 2 byte
int b; // allocates 4 bytes
char ch2; // allocates 2 byte
};
cout << sizeof(MyStruct2); // displays 12
#pragma pack(4)
struct MyStruct3
{
int a; // allocates 4 bytes
char ch1; // allocates 4 byte
int b; // allocates 4 bytes
char ch2; // allocates 4 byte
};
cout << sizeof(MyStruct3); // displays 16 In the above example, to read the value of b, we need only one IO read cycles in 32 bit machine because of its memory alignment.
C++ - Comma Operator
Comma is an operator in C++. When comma is with in paranthesis, the right most argument is taken as a result otherwise left most.
int a, b, m , n;
a = 10;
b = 20;
m = (a,b); // m will hold the value of b which is 20
n = a,b; // m will hold the value of b which is 10
std::cout << m, n; // The code prints the output 20,10
int a, b, m , n;
a = 10;
b = 20;
m = (a,b); // m will hold the value of b which is 20
n = a,b; // m will hold the value of b which is 10
std::cout << m, n; // The code prints the output 20,10
C++ - Static Variables
Variables can be declared in stack or heap or static. Static variables means the memory is allocated statically and its life time is throughout the program execution time.
If a variable is allocated on the stack, we can see that stack size is increasing. If a variable is allocated on the heap (example using new operator in C++ or malloc in C), we can see that heap size if increasing.
If I allocate a variable of 100 KB in static, which size will increase? Stack or Heap? Both are not correct. Your size of the .EXE file will increase..! This might be a surprise to many programmers in the begining. Similarly global variables are also allocated like static variables and its life time is throughout the program execution time.
Example for static variabales allocation is given below:
#include <iostream>
static char msg[] = "Welcome to my static function";
void DisplayWelcomeMessage()
{
std::cout << msg;
// Accessing the msg static variable in sub function in the current file
}
int main()
{
// Accessing the msg static variable in main function in the current file
std::cout << msg;
}
Can I have a static variable in a class? Of course, YES. You can have any number of static variables. The use of static variable is all the instance of the class objects can share the same object.
In fact if it is a public static variable, you do not even need any class object to access the member. You can access it by <class name>::<static variable name>.
Writing class is only a declaration and it does not allocate any memory. When you create an instance, the memory is allocated. How come static member variables of class gets allocated? You need to allocate explicitly by defining the member variable. Look at the following example on how m_pMySingletonClass is defined.
#include <iostream>
class MySingletonClass {
private:
int m_nValue;
MySingletonClass() { };
MySingletonClass(const MySingletonClass& other);
const MySingletonClass& operator = (const MySingletonClass& other);
public:
static MySingletonClass* m_pMySingletonClass;
static MySingletonClass* GetInstance()
{
if(m_pMySingletonClass == NULL)
m_pMySingletonClass = new MySingletonClass();
return m_pMySingletonClass;
}
int GetValue() const { return m_nValue; }
void SetValue(int nVal) { m_nValue = nVal; }
};
// Defining the static member variable m_pMySingletonClass
MySingletonClass* MySingletonClass::m_pMySingletonClass = NULL;
int main()
{
MySingletonClass *p1 = MySingletonClass::GetInstance();
MySingletonClass *p2 = MySingletonClass::GetInstance();
p1->SetValue(100);
std::cout << p2->GetValue(); // Displays 100 on the screen
}
If a variable is allocated on the stack, we can see that stack size is increasing. If a variable is allocated on the heap (example using new operator in C++ or malloc in C), we can see that heap size if increasing.
If I allocate a variable of 100 KB in static, which size will increase? Stack or Heap? Both are not correct. Your size of the .EXE file will increase..! This might be a surprise to many programmers in the begining. Similarly global variables are also allocated like static variables and its life time is throughout the program execution time.
Example for static variabales allocation is given below:
#include <iostream>
static char msg[] = "Welcome to my static function";
void DisplayWelcomeMessage()
{
std::cout << msg;
// Accessing the msg static variable in sub function in the current file
}
int main()
{
// Accessing the msg static variable in main function in the current file
std::cout << msg;
}
Can I have a static variable in a class? Of course, YES. You can have any number of static variables. The use of static variable is all the instance of the class objects can share the same object.
In fact if it is a public static variable, you do not even need any class object to access the member. You can access it by <class name>::<static variable name>.
Writing class is only a declaration and it does not allocate any memory. When you create an instance, the memory is allocated. How come static member variables of class gets allocated? You need to allocate explicitly by defining the member variable. Look at the following example on how m_pMySingletonClass is defined.
#include <iostream>
class MySingletonClass {
private:
int m_nValue;
MySingletonClass() { };
MySingletonClass(const MySingletonClass& other);
const MySingletonClass& operator = (const MySingletonClass& other);
public:
static MySingletonClass* m_pMySingletonClass;
static MySingletonClass* GetInstance()
{
if(m_pMySingletonClass == NULL)
m_pMySingletonClass = new MySingletonClass();
return m_pMySingletonClass;
}
int GetValue() const { return m_nValue; }
void SetValue(int nVal) { m_nValue = nVal; }
};
// Defining the static member variable m_pMySingletonClass
MySingletonClass* MySingletonClass::m_pMySingletonClass = NULL;
int main()
{
MySingletonClass *p1 = MySingletonClass::GetInstance();
MySingletonClass *p2 = MySingletonClass::GetInstance();
p1->SetValue(100);
std::cout << p2->GetValue(); // Displays 100 on the screen
}
C++ - Static Functions
Static functions in a file restricts the access level to the functions on that file only.
Example for static function is given below:
#include <iostream>
static const char* GetWelcomeMessage()
{
static char msg[] = "Welcome to my static function";
return msg;
}
int main()
{
// GetWelcomeMessage can only be accessed in the current .CPP file
std::cout << GetWelcomeMessage();
// It will display Welcome to my static function as output
}
Can I have a static function in a class? Of course, YES. You can have any number of static function. If it is a public static function, you do not even need any class object to access the static member function. You can access it by <class name>::<static function name>.
A typical example for static function is singleton class. static MySingletonClass* GetInstance() is a static member function in the class and it is used in the main function.
#include <iostream>
class MySingletonClass {
private:
int m_nValue;
MySingletonClass() { };
MySingletonClass(const MySingletonClass& other);
const MySingletonClass& operator = (const MySingletonClass& other);
public:
static MySingletonClass* m_pMySingletonClass;
static MySingletonClass* GetInstance()
{
if(m_pMySingletonClass == NULL)
m_pMySingletonClass = new MySingletonClass();
return m_pMySingletonClass;
}
int GetValue() const { return m_nValue; }
void SetValue(int nVal) { m_nValue = nVal; }
};
MySingletonClass* MySingletonClass::m_pMySingletonClass = NULL;
int main()
{
// Accessing static function GetInstance()
MySingletonClass *p1 = MySingletonClass::GetInstance();
MySingletonClass *p2 = MySingletonClass::GetInstance();
// Both instances will point to the same object
p1->SetValue(100);
std::cout << p2->GetValue();
}
Example for static function is given below:
#include <iostream>
static const char* GetWelcomeMessage()
{
static char msg[] = "Welcome to my static function";
return msg;
}
int main()
{
// GetWelcomeMessage can only be accessed in the current .CPP file
std::cout << GetWelcomeMessage();
// It will display Welcome to my static function as output
}
Can I have a static function in a class? Of course, YES. You can have any number of static function. If it is a public static function, you do not even need any class object to access the static member function. You can access it by <class name>::<static function name>.
A typical example for static function is singleton class. static MySingletonClass* GetInstance() is a static member function in the class and it is used in the main function.
#include <iostream>
class MySingletonClass {
private:
int m_nValue;
MySingletonClass() { };
MySingletonClass(const MySingletonClass& other);
const MySingletonClass& operator = (const MySingletonClass& other);
public:
static MySingletonClass* m_pMySingletonClass;
static MySingletonClass* GetInstance()
{
if(m_pMySingletonClass == NULL)
m_pMySingletonClass = new MySingletonClass();
return m_pMySingletonClass;
}
int GetValue() const { return m_nValue; }
void SetValue(int nVal) { m_nValue = nVal; }
};
MySingletonClass* MySingletonClass::m_pMySingletonClass = NULL;
int main()
{
// Accessing static function GetInstance()
MySingletonClass *p1 = MySingletonClass::GetInstance();
MySingletonClass *p2 = MySingletonClass::GetInstance();
// Both instances will point to the same object
p1->SetValue(100);
std::cout << p2->GetValue();
}
Turbo C++ - Union of Two Arrays
Here is the Turbo C++ source code for union of two arrays which means finding the union of elements between two arrays. The good thing about this coding is it will allocate only the required memory. During the first iterator it will count how many number of unique elements are available in two arrays. Then use the formula
"array1 unique count + array2 unique count - intersection of array1 and array2 elements count"
to allocate the memory and fill in the elements in its second iteration.
Source Code#include <stdio.h>
#include <iostream.h>
typedef enum boolean {
false, true
} bool;
int array1[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
95, 85, 75, 65, 55, 45, 35, 25, 15, 05,
10, 15, 20, 25, 30, 35, 40, 45, 50, 55
};
int array2[] = { 15, 25, 35, 45, 55,
12, 22, 32, 43, 52,
15, 25, 35, 45, 55
};
typedef struct _Array
{
int *elements;
int len;
_Array()
{
elements = NULL;
len = 0;
}
_Array(int *data, int len);
_Array(int len)
{
this->len = len;
this->elements = new int[len];
}
~_Array()
{
if(this->elements != NULL)
{
delete [] this->elements;
this->elements = NULL;
this->len = 0;
}
}
} Array;
_Array::_Array(int *data, int len)
{
this->elements = new int[len];
this->len = len;
for(int i = 0; i < len; i++)
this->elements[i] = data[i];
}
// Find the array Intersection = Common Elements from two arrays
Array* Find_Common_Elements(Array *p1, Array *p2)
{
int count = 0;
for(int i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
count++;
break;
}
}
}
Array *result = new Array(count);
count = 0;
for(i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
result->elements[count++] = p1->elements[i];
break;
}
}
}
return result;
}
Array* BubbleSort(Array *p)
{
for(int i = 1; i < p->len; i++)
{
for(int j = 0; j < p->len - i; j++)
{
if(p->elements[j] > p->elements[j + 1])
{
int temp = p->elements[j];
p->elements[j] = p->elements[j + 1];
p->elements[j + 1] = temp;
}
}
}
return p;
}
// Union of two unique arrays
Array* Union_Array(Array *p1, Array *p2)
{
int count = p1->len + p2->len;
Array *temp = Find_Common_Elements(p1, p2);
count = count - temp->len;
Array *result = new Array(count);
count = 0;
for(int i = 0; i < p1->len; i++)
result->elements[count++] = p1->elements[i];
for(int j = 0; j < p2->len; j++)
{
bool bInclude = true;
for(int k = 0; k < temp->len; k++)
{
if(temp->elements[k] == p2->elements[j])
{
bInclude = false;
break;
}
}
if(bInclude == true)
result->elements[count++] = p2->elements[j];
}
return BubbleSort(result);
}
Array* Find_Unique_Elements(Array *p)
{
BubbleSort(p);
int element = p->elements[0];
int count = 1;
for(int i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
count++;
}
}
Array *result = new Array(count);
count = 0;
element = p->elements[0];
result->elements[count++] = element;
for(i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
result->elements[count++] = element;
}
}
return result;
}
int main()
{
Array *a1 = new Array(array1, sizeof(array1) / sizeof(array1[0]));
Array *a2 = new Array(array2, sizeof(array2) / sizeof(array2[0]));
Array *p1 = Find_Unique_Elements(a1);
Array *p2 = Find_Unique_Elements(a2);
Array *result = Union_Array(p1, p2);
cout << "\n\nUnique Sorted Elements in Array1: ";
for(int i = 0; i < p1->len; i++)
cout << p1->elements[i] << " ";
cout << "\n\nUnique Sorted Elements in Array2: ";
for(i = 0; i < p2->len; i++)
cout << p2->elements[i] << " ";
cout << "\n\nUnion of Elements in Array1 and Array2: ";
for(i = 0; i < result->len; i++)
cout << result->elements[i] << " ";
cout << "\n\n";
delete a1, a2, p1, p2, result;
return 0;
}
"array1 unique count + array2 unique count - intersection of array1 and array2 elements count"
to allocate the memory and fill in the elements in its second iteration.
Source Code#include <stdio.h>
#include <iostream.h>
typedef enum boolean {
false, true
} bool;
int array1[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
95, 85, 75, 65, 55, 45, 35, 25, 15, 05,
10, 15, 20, 25, 30, 35, 40, 45, 50, 55
};
int array2[] = { 15, 25, 35, 45, 55,
12, 22, 32, 43, 52,
15, 25, 35, 45, 55
};
typedef struct _Array
{
int *elements;
int len;
_Array()
{
elements = NULL;
len = 0;
}
_Array(int *data, int len);
_Array(int len)
{
this->len = len;
this->elements = new int[len];
}
~_Array()
{
if(this->elements != NULL)
{
delete [] this->elements;
this->elements = NULL;
this->len = 0;
}
}
} Array;
_Array::_Array(int *data, int len)
{
this->elements = new int[len];
this->len = len;
for(int i = 0; i < len; i++)
this->elements[i] = data[i];
}
// Find the array Intersection = Common Elements from two arrays
Array* Find_Common_Elements(Array *p1, Array *p2)
{
int count = 0;
for(int i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
count++;
break;
}
}
}
Array *result = new Array(count);
count = 0;
for(i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
result->elements[count++] = p1->elements[i];
break;
}
}
}
return result;
}
Array* BubbleSort(Array *p)
{
for(int i = 1; i < p->len; i++)
{
for(int j = 0; j < p->len - i; j++)
{
if(p->elements[j] > p->elements[j + 1])
{
int temp = p->elements[j];
p->elements[j] = p->elements[j + 1];
p->elements[j + 1] = temp;
}
}
}
return p;
}
// Union of two unique arrays
Array* Union_Array(Array *p1, Array *p2)
{
int count = p1->len + p2->len;
Array *temp = Find_Common_Elements(p1, p2);
count = count - temp->len;
Array *result = new Array(count);
count = 0;
for(int i = 0; i < p1->len; i++)
result->elements[count++] = p1->elements[i];
for(int j = 0; j < p2->len; j++)
{
bool bInclude = true;
for(int k = 0; k < temp->len; k++)
{
if(temp->elements[k] == p2->elements[j])
{
bInclude = false;
break;
}
}
if(bInclude == true)
result->elements[count++] = p2->elements[j];
}
return BubbleSort(result);
}
Array* Find_Unique_Elements(Array *p)
{
BubbleSort(p);
int element = p->elements[0];
int count = 1;
for(int i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
count++;
}
}
Array *result = new Array(count);
count = 0;
element = p->elements[0];
result->elements[count++] = element;
for(i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
result->elements[count++] = element;
}
}
return result;
}
int main()
{
Array *a1 = new Array(array1, sizeof(array1) / sizeof(array1[0]));
Array *a2 = new Array(array2, sizeof(array2) / sizeof(array2[0]));
Array *p1 = Find_Unique_Elements(a1);
Array *p2 = Find_Unique_Elements(a2);
Array *result = Union_Array(p1, p2);
cout << "\n\nUnique Sorted Elements in Array1: ";
for(int i = 0; i < p1->len; i++)
cout << p1->elements[i] << " ";
cout << "\n\nUnique Sorted Elements in Array2: ";
for(i = 0; i < p2->len; i++)
cout << p2->elements[i] << " ";
cout << "\n\nUnion of Elements in Array1 and Array2: ";
for(i = 0; i < result->len; i++)
cout << result->elements[i] << " ";
cout << "\n\n";
delete a1, a2, p1, p2, result;
return 0;
}
Turbo C++ - Intersection of Two Arrays
Here is the Turbo C++ source code intersection of two arrays which means finding the common elements between two arrays. The good thing about this coding is it will allocate only the required memory. During the first iterator it will count how many number of unique elements and common elements are available in an array. Then use the count to allocate the memory and fill in the elements in its second iteration.
Source Code#include <stdio.h>
#include <iostream.h>
typedef enum boolean {
false, true
} bool;
int array1[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
95, 85, 75, 65, 55, 45, 35, 25, 15, 05,
10, 15, 20, 25, 30, 35, 40, 45, 50, 55
};
int array2[] = { 15, 25, 35, 45, 55,
12, 22, 32, 43, 52,
15, 25, 35, 45, 55
};
typedef struct _Array
{
int *elements;
int len;
_Array()
{
elements = NULL;
len = 0;
}
_Array(int *data, int len);
_Array(int len)
{
this->len = len;
this->elements = new int[len];
}
~_Array()
{
if(this->elements != NULL)
{
delete [] this->elements;
this->elements = NULL;
this->len = 0;
}
}
} Array;
_Array::_Array(int *data, int len)
{
this->elements = new int[len];
this->len = len;
for(int i = 0; i < len; i++)
this->elements[i] = data[i];
}
// Find the array Intersection = Common Elements from two arrays
Array* Find_Common_Elements(Array *p1, Array *p2)
{
int count = 0;
for(int i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
count++;
break;
}
}
}
Array *result = new Array(count);
count = 0;
for(i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
result->elements[count++] = p1->elements[i];
break;
}
}
}
return result;
}
Array* BubbleSort(Array *p)
{
for(int i = 1; i < p->len; i++)
{
for(int j = 0; j < p->len - i; j++)
{
if(p->elements[j] > p->elements[j + 1])
{
int temp = p->elements[j];
p->elements[j] = p->elements[j + 1];
p->elements[j + 1] = temp;
}
}
}
return p;
}
Array* Find_Unique_Elements(Array *p)
{
BubbleSort(p);
int element = p->elements[0];
int count = 1;
for(int i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
count++;
}
}
Array *result = new Array(count);
count = 0;
element = p->elements[0];
result->elements[count++] = element;
for(i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
result->elements[count++] = element;
}
}
return result;
}
int main()
{
Array *a1 = new Array(array1, sizeof(array1) / sizeof(array1[0]));
Array *a2 = new Array(array2, sizeof(array2) / sizeof(array2[0]));
Array *p1 = Find_Unique_Elements(a1);
Array *p2 = Find_Unique_Elements(a2);
Array *result = Find_Common_Elements(p1, p2);
cout << "\n\nUnique Sorted Elements in Array1: ";
for(int i = 0; i < p1->len; i++)
cout << p1->elements[i] << " ";
cout << "\n\nUnique Sorted Elements in Array2: ";
for(i = 0; i < p2->len; i++)
cout << p2->elements[i] << " ";
cout << "\n\nCommon (Intersection of) Elements in Array1 and Array2: ";
for(i = 0; i < result->len; i++)
cout << result->elements[i] << " ";
cout << "\n\n";
delete a1, a2, p1, p2, result;
return 0;
}
Source Code#include <stdio.h>
#include <iostream.h>
typedef enum boolean {
false, true
} bool;
int array1[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
95, 85, 75, 65, 55, 45, 35, 25, 15, 05,
10, 15, 20, 25, 30, 35, 40, 45, 50, 55
};
int array2[] = { 15, 25, 35, 45, 55,
12, 22, 32, 43, 52,
15, 25, 35, 45, 55
};
typedef struct _Array
{
int *elements;
int len;
_Array()
{
elements = NULL;
len = 0;
}
_Array(int *data, int len);
_Array(int len)
{
this->len = len;
this->elements = new int[len];
}
~_Array()
{
if(this->elements != NULL)
{
delete [] this->elements;
this->elements = NULL;
this->len = 0;
}
}
} Array;
_Array::_Array(int *data, int len)
{
this->elements = new int[len];
this->len = len;
for(int i = 0; i < len; i++)
this->elements[i] = data[i];
}
// Find the array Intersection = Common Elements from two arrays
Array* Find_Common_Elements(Array *p1, Array *p2)
{
int count = 0;
for(int i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
count++;
break;
}
}
}
Array *result = new Array(count);
count = 0;
for(i = 0; i < p1->len; i++)
{
for(int j = 0; j < p2->len; j++)
{
if(p1->elements[i] == p2->elements[j])
{
result->elements[count++] = p1->elements[i];
break;
}
}
}
return result;
}
Array* BubbleSort(Array *p)
{
for(int i = 1; i < p->len; i++)
{
for(int j = 0; j < p->len - i; j++)
{
if(p->elements[j] > p->elements[j + 1])
{
int temp = p->elements[j];
p->elements[j] = p->elements[j + 1];
p->elements[j + 1] = temp;
}
}
}
return p;
}
Array* Find_Unique_Elements(Array *p)
{
BubbleSort(p);
int element = p->elements[0];
int count = 1;
for(int i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
count++;
}
}
Array *result = new Array(count);
count = 0;
element = p->elements[0];
result->elements[count++] = element;
for(i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
result->elements[count++] = element;
}
}
return result;
}
int main()
{
Array *a1 = new Array(array1, sizeof(array1) / sizeof(array1[0]));
Array *a2 = new Array(array2, sizeof(array2) / sizeof(array2[0]));
Array *p1 = Find_Unique_Elements(a1);
Array *p2 = Find_Unique_Elements(a2);
Array *result = Find_Common_Elements(p1, p2);
cout << "\n\nUnique Sorted Elements in Array1: ";
for(int i = 0; i < p1->len; i++)
cout << p1->elements[i] << " ";
cout << "\n\nUnique Sorted Elements in Array2: ";
for(i = 0; i < p2->len; i++)
cout << p2->elements[i] << " ";
cout << "\n\nCommon (Intersection of) Elements in Array1 and Array2: ";
for(i = 0; i < result->len; i++)
cout << result->elements[i] << " ";
cout << "\n\n";
delete a1, a2, p1, p2, result;
return 0;
}
Turbo C++ - Find Unique Elements from an array
Here is the Turbo C++ source code for Finding the Unique Elements in an Array with efficient memory usage. The good thing about this coding is it will allocate only the required memory. During the first iterator it will count how many number of unique elemnts are available in an array. Then use the count to allocate the memory and fill in the elements in its second iteration.
Source Code#include <stdio.h>
#include <iostream.h>
typedef enum boolean {
false, true
} bool;
int array1[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
95, 85, 75, 65, 55, 45, 35, 25, 15, 05,
10, 15, 20, 25, 30, 35, 40, 45, 50, 55
};
int array2[] = { 15, 25, 35, 45, 55,
12, 22, 32, 43, 52,
15, 25, 35, 45, 55
};
typedef struct _Array
{
int *elements;
int len;
_Array()
{
elements = NULL;
len = 0;
}
_Array(int *data, int len);
_Array(int len)
{
this->len = len;
this->elements = new int[len];
}
~_Array()
{
if(this->elements != NULL)
{
delete [] this->elements;
this->elements = NULL;
this->len = 0;
}
}
} Array;
_Array::_Array(int *data, int len)
{
this->elements = new int[len];
this->len = len;
for(int i = 0; i < len; i++)
this->elements[i] = data[i];
}
Array* BubbleSort(Array *p)
{
for(int i = 1; i < p->len; i++)
{
for(int j = 0; j < p->len - i; j++)
{
if(p->elements[j] > p->elements[j + 1])
{
int temp = p->elements[j];
p->elements[j] = p->elements[j + 1];
p->elements[j + 1] = temp;
}
}
}
return p;
}
Array* Find_Unique_Elements(Array *p)
{
BubbleSort(p);
int element = p->elements[0];
int count = 1;
for(int i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
count++;
}
}
Array *result = new Array(count);
count = 0;
element = p->elements[0];
result->elements[count++] = element;
for(i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
result->elements[count++] = element;
}
}
return result;
}
int main()
{
Array *a1 = new Array(array1, sizeof(array1) / sizeof(array1[0]));
Array *a2 = new Array(array2, sizeof(array2) / sizeof(array2[0]));
Array *p1 = Find_Unique_Elements(a1);
Array *p2 = Find_Unique_Elements(a2);
cout << "\n\nUnique Sorted Elements in Array1: ";
for(int i = 0; i < p1->len; i++)
cout << p1->elements[i] << " ";
cout << "\n\nUnique Sorted Elements in Array2: ";
for(i = 0; i < p2->len; i++)
cout << p2->elements[i] << " ";
delete a1, a2, p1, p2, result;
return 0;
}
Source Code#include <stdio.h>
#include <iostream.h>
typedef enum boolean {
false, true
} bool;
int array1[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
95, 85, 75, 65, 55, 45, 35, 25, 15, 05,
10, 15, 20, 25, 30, 35, 40, 45, 50, 55
};
int array2[] = { 15, 25, 35, 45, 55,
12, 22, 32, 43, 52,
15, 25, 35, 45, 55
};
typedef struct _Array
{
int *elements;
int len;
_Array()
{
elements = NULL;
len = 0;
}
_Array(int *data, int len);
_Array(int len)
{
this->len = len;
this->elements = new int[len];
}
~_Array()
{
if(this->elements != NULL)
{
delete [] this->elements;
this->elements = NULL;
this->len = 0;
}
}
} Array;
_Array::_Array(int *data, int len)
{
this->elements = new int[len];
this->len = len;
for(int i = 0; i < len; i++)
this->elements[i] = data[i];
}
Array* BubbleSort(Array *p)
{
for(int i = 1; i < p->len; i++)
{
for(int j = 0; j < p->len - i; j++)
{
if(p->elements[j] > p->elements[j + 1])
{
int temp = p->elements[j];
p->elements[j] = p->elements[j + 1];
p->elements[j + 1] = temp;
}
}
}
return p;
}
Array* Find_Unique_Elements(Array *p)
{
BubbleSort(p);
int element = p->elements[0];
int count = 1;
for(int i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
count++;
}
}
Array *result = new Array(count);
count = 0;
element = p->elements[0];
result->elements[count++] = element;
for(i = 1; i < p->len; i++)
{
if(element == p->elements[i])
continue;
else
{
element = p->elements[i];
result->elements[count++] = element;
}
}
return result;
}
int main()
{
Array *a1 = new Array(array1, sizeof(array1) / sizeof(array1[0]));
Array *a2 = new Array(array2, sizeof(array2) / sizeof(array2[0]));
Array *p1 = Find_Unique_Elements(a1);
Array *p2 = Find_Unique_Elements(a2);
cout << "\n\nUnique Sorted Elements in Array1: ";
for(int i = 0; i < p1->len; i++)
cout << p1->elements[i] << " ";
cout << "\n\nUnique Sorted Elements in Array2: ";
for(i = 0; i < p2->len; i++)
cout << p2->elements[i] << " ";
delete a1, a2, p1, p2, result;
return 0;
}