In this tutorial you will learn the basics of C++ and how to use members and exceptions. This will allow you to write a simple C++ program that you will then compile. The program will be a Visual Studio console application
About this Tutorial –
Objectives –
This course is aimed at students who need to get up to speed in C++. The course introduces object-oriented concepts and shows how they are implemented in C++. The course does not require awareness or familiarity with object-oriented programming techniques, but programming experience would be useful but not necessarily required.
Audience
Students who are new to object orientation (or programming) and need to learn C++.
Prerequisites
No previous experience in C++ programming is required. But any experience you do have in programming will help. Also no experience in Visual Studio is required. But again any experience you do have with programming development environments will be a valuable.
Experience using a contemporary OO language such as Java or C# would be useful but is not required.
Contents
The C++ course covers these topics and more:
- Introduction to C++: Key features of C++; Defining variables; Formulating expressions and statements; Built-in data types; Console input/output
- Operators and types: Assignment; Compound Assignment; Increment and decrement operators; Const declarations; Type conversions
- Going Further with Data Types: Enumerations; Arrays; Using the standard vector class; Using the standard string class; Structures
Overview
Estimated Time – 0.5 Hours
Not what you are looking? Try the next tutorial – Dynamic Arrays and Vectors
Lab 1: Construction and destruction
- A Reminder about Constructors
- A constructor is a special initialization function in a class
- Same name as class
- Might take parameters, but has no return type
- Invoked implicitly by the compiler, to guarantee an object is properly initialization when created
- Here’s a simple example from before:
// Header
class BankAccount
{
string accountHolder;
int id;
double balance;
...
public:
BankAccount(string ah);
...
};
// Cpp File
#include "BankAccount.h"
BankAccount::BankAccount(string ah)
{
accountHolder = ah;
id = -1;
balance = 0;
}
- A constructor is a special initialization function in a class
- Member Initialization Lists
- For constructors, there’s an alternative syntax for initializing members
- Known as a “member initialization list”
- This is actually the preferred way to perform initialization, the reasons will become apparent in due course
- This is the syntax for a member initialization list
- You use member initialization lists on the function implementation (not on the function prototype)
#include "BankAccount.h"
BankAccount::BankAccount(string ah) : accountHolder(ah), id(-1), balance(0)
{
// Do any additional "algorithmic" initialization here if necessary
cout << "I have just initialized " << accountHolder << endl; }
- You use member initialization lists on the function implementation (not on the function prototype)
- For constructors, there’s an alternative syntax for initializing members
- Destructors
- A destructor is a special "on destruction" function in a class
- Same name as class, preceded by ~
- No parameters, no return type
- Invoked implicitly by the compiler just before an object is destroyed, to allow the object to do any additional tidying up
- Here's a simple example:
// Header
class BankAccount
{
...
public:
~BankAccount();
..
};
// Cpp File
#include "BankAccount.h"
BankAccount::~BankAccount()
{
cout << "Destroying account " << accountHolder << endl; }
- A destructor is a special "on destruction" function in a class
- Defining a "starter" class
- In Visual Studio, create a new C++ project named GoingFurtherWithClassesApp in the student folder
- Implement a class named LoginDetails with the following members:
- Data members for the user's username and password.
// Header
string username;
string password;
- A constructor, to initialize both data members.
// header
LoginDetails(const string & username, const string & password);
// CPP
LoginDetails::LoginDetails(const string & username, const string & password)
: username(username), password(password){}
- A Display() method, to display the username and password (for testing purposes!)
// Header
void Display() const;
// CPP
void LoginDetails::Display() const
{
cout << "Username: " << username << ", password: " << password << endl << endl; } - View code file.
- View code file.
- A ChangePassword() method. The method should take parameters specifying the current password and a new password. If the current password parameter is correct, the method should change the password to the new password
// Header
bool ChangePassword(const string & oldPassword, const string & newPassword);
// CPP
bool LoginDetails::ChangePassword(const string & oldPassword, const string & newPassword)
{
if (oldPassword == password)
{
password = newPassword;
return true;
}
else
{
return false;
}
}
- View code file.
- View code file.
- Data members for the user's username and password.
- In main(),write some simple code to test your LoginDetails class.
LoginDetails me("Tarzan", "password1");
cout << "Result of invalid attempt to change password: " << me.ChangePassword("hurrumphy", "newpassword1") << endl; cout << "Result of valid attempt to change password: " << me.ChangePassword("password1", "newpassword1") << endl; me.Display(); - View code file.
Lab 2: Static members
- Defining Static Variables
- static variables belong to the class as a whole
- Allocated once, before first usage of class
- Remain allocated regardless of number of instances
- You declare static members in the header file:
class BankAccount
{
private:
static int nextId;
public:
static const double OVERDRAFT_LIMIT;
...
};
- You must also define static members in the source file:
int BankAccount::nextId = 1;
const double BankAccount::OVERDRAFT_LIMIT = -1000;
- static variables belong to the class as a whole
- Using Static Variables
- Client code can access public static variables via the class name
- Use the scope resolution operator ::
cout << "Overdraft limit is " << BankAccount::OVERDRAFT_LIMIT << endl;
- Use the scope resolution operator ::
- Client code can access public static variables via the class name
- Defining Static Methods
- Using Static Methods
- Defining const data members
- Exercise 2: Defining const data members
Modify your LoginDetails class as follows:- Make the username a const data member
const string username;
- Experiment with different ways to set this member (e.g. in the constructor's member initialization list, in the constructor's body, in a separate method, etc.). Where are you allowed to set the const data member?
// Example
LoginDetails::LoginDetails(const string & username, const string & password): username(username), password(password)
{
// This statement fails to compile - can't modify const data member.
// this->username = username;
}
- View code file.
- View code file.
- Make the username a const data member
- Exercise 2: Defining const data members
Lab 3: Dynamic object creation/deletion
- Reminder about Creating Objects
- We've already seen you can just create objects like this:
void myFunc()
{
BankAccount myAcc;
BankAccount yourAcc("John");
// Use the objects.
myAcc.Withdraw(100);
yourAcc.Deposit(200);
...
}
- We've already seen you can just create objects like this:
- Creating Dynamic Objects
- Sometimes you want an object to live beyond the end of the current function (!)
- To achieve this effect, you must allocate the function dynamically via the new keyword
- Allocates the object on the "heap"
- Calls an appropriate constructor
- Returns a pointer
void myFunc()
{
BankAccount * pMyAcc = new BankAccount; // Calls no-arg ctor.
BankAccount * pYourAcc = new BankAccount("John"); // Calls parameterized ctor.
// Use the objects, via pointers now!
pMyAcc->Withdraw(100);
pYourAcc->Deposit(200);
...
}
- Deleting Dynamic Objects
- If you create an object using new, somewhere you must remember to delete it yourself
- Use delete, followed by the pointer to the object to be deleted
- Calls the object's destructor
- Then frees the object's memory on the heap
BankAccount *pMyAcc = 0;
BankAccount *pYourAcc = 0;
// Allocate objects via "new", and store addresses in pMyAcc and pYourAcc.
...
// When we are ready, delete the objects via the pointers.
delete pMyAcc;
delete pYourAcc;
- Note for Java/C# developers:
- There is no garbage collection in C++!
- If you create an object using new, somewhere you must remember to delete it yourself
- Defining static members
- Modify your LoginDetails class as follows:
- Define a class-wide (i.e. static) data member to hold a "master" password. This is like a master key - it allows anyone to see anyone else's password (like an administrator). Set this data member to the magic word, i.e. "please"
//Header
static string masterPassword;
// CPP
string LoginDetails::masterPassword = "please";
- Define another class-wide (i.e. static) data member to hold a "default" password.
// Header
static string defaultPassword;
// CPP
string LoginDetails::defaultPassword = "defaultPassword";
- Allow the user to create a LoginDetails object by just specifying their username (tell them their default password)
LoginDetails(const string & username, const string & password = defaultPassword);
- Define a class-wide (i.e. static) method to display the "master" and "default" passwords
// Header
static void DisplayClassPasswords();
// CPP
cout << "Master password: " << masterPassword << endl; cout << "Default password: " << defaultPassword << endl; - View code file.
- View code file.
- Define a class-wide (i.e. static) data member to hold a "master" password. This is like a master key - it allows anyone to see anyone else's password (like an administrator). Set this data member to the magic word, i.e. "please"
- Test the new functionality from main()
LoginDetails you("Jane");
you.Display();
LoginDetails::DisplayClassPasswords();
- View code file.
- Modify your LoginDetails class as follows:
Lab 4: Miscellaneous class techniques
- Member Functions
- C++ supports the notion of "const member functions"
- The compiler checks that a const member function really doesn't modify the target object
- If it does, you'll get a compiler error!
- Const member functions are really important!!!
- Every time you add a new member function to a class, ask yourself "should I declare this as a const member function?"
- It makes it much easier for the client programmer to know which functions are likely to change their objects
- To define a const member function:
- In the class declaration, append the const keyword after the closing ) in the method signature
class BankAccount
{
double GetBalance() const;
...
};
- You must also add the const keyword after the closing ) in the method implementation
double BankAccount::GetBalance() const
{
// You have read-only access to members of "this" object here...
return balance;
// But you'd get a compiler error if you changed any member of "this" object...
// balance += 100; NO!!!
}
- In the class declaration, append the const keyword after the closing ) in the method signature
- Inline Functions
- Up until now, you've implemented all functions in .cpp files
double BankAccount::GetBalance() const
{
return balance;
}
- When the client program calls these functions
- Flow-of-control passes into the function
- Parameters are passed into the function if necessary
- The function does its thing
- After the } at the end of the function, flow of control returns to the caller function
- For very small functions (like "getters")
- The amount of effort getting into the function and then returning from the function far outweighs the amount of time spent inside the function itself!
- In this case, you can declare the function "inline"
- Tells the compiler "don't actually jump into this function at runtime, instead paste the body of the function inline into the client code"
- Avoids the overhead of a function call / return
- Appropriate for the very smallest of functions (typically the getters)
- Preferred way to declare an inline function:
class BankAccount
{
double GetBalance() const;
...
};
inline double BankAccount::GetBalance() const
{
return balance;
}
- Alternative approach (familiar for Java/C# developers):
class BankAccount
{
double GetBalance() const
{
return balance;
}
...
};
- Up until now, you've implemented all functions in .cpp files
- Nested Classes
- C++ allows you to define nested classes
- The nested class can be public, private, or protected
class List
{
public:
class Node
{
private:
int data;
Node *pNext;
Node *pPrev;
public:
Node(int data, Node *pNext, Node *pPrev);
int GetData() const;
};
List();
~List();
void Append(int data);
const Node * GetHeadNode() const;
int PopHeadData();
private:
Node * pHead;
};
- The nested class can be public, private, or protected
- C++ allows you to define nested classes
Lab 5: Exception handling
- Overview of Exceptions
- Exceptions are a run-time mechanism for indicating exceptional conditions in C++
- If you detect an exceptional condition, you can throw an exception
- An exception is an object that contains relevant error info
- Somewhere up the call stack, the exception is caught and dealt with
- If the exception is not caught, your application terminates
- Note: C++ doesn't support "checked exception"
- A method doesn't have to declare what exceptions it might throw
- Client code isn't obliged (by the compiler) to catch any exceptions
- Exceptions are a run-time mechanism for indicating exceptional conditions in C++
- Standard Exceptions in C++
- A closer Look at the exception Class
- exception is the root exception class in C++
- All the standard C++ exception classes inherit from exception
- Custom exception classes should inherit from exception too
class exception
{
public:
exception() throw();
exception(const exception & innerException) throw();
virtual ~exception() throw();
exception & operator=(const exception & other) throw();
virtual const char * what() const throw();
...
};
- Note:
- exception is the root exception class in C++
- How to Throw and Catch Exceptions
- try block
- Contains code that might cause an exception
- throw keyword
- Throws an exception object
- catch block(s)
- One or more
- Specify an exception class, to catch exception object
- Perform recovery code
try
{
// Code that might cause an exception ...
throw SomeExceptionType(someParams);
}
catch (ExceptionType1 & ex)
{
// Code to handle ExceptionType1 ...
}
catch (ExceptionType2 & ex)
{
// Code to handle ExceptionType2 ...
}
- Note:
- There is no concept of finally blocks in C++
- achieve exception safety, implement appropriate destructors
- try block
- Catching a Hierarchy of Exceptions
- When you define a catch handler...
- It will catch that exception type, plus any subclasses
- You can define multiple catch handlers
- When an exception occurs, catch handlers are tried in sequence, looking for a suitable handler
- You should organize your catch handlers from specific to general
try
{
...
}
catch (bad_alloc & ex)
{
...
}
catch (exception & ex)
{
...
}
- When you define a catch handler...
- Catching any Type of Exception
- You can define a catch-all handler
- Define a catch handler with ... as the exception type
try
{
...
}
catch (ExceptionType1 & ex)
{
...
}
catch (ExceptionType2 & ex)
{
...
}
catch (...) // Catch-all handler, note the ... here is real syntax!
{
// Do general-purpose exception processing.
}
- Define a catch handler with ... as the exception type
- You can define a catch-all handler
- Re-throwing an Exception
- Imagine you're writing a low-level library class...
- Lots of exceptions might occur
- You want to catch the exception locally, to do some intermediate processing (e.g. log the exception)
- You also want to force the caller to do "full" processing
- You can catch and re-throw an exception:
- Do some local processing
- The re-throw the same exception, using just the throw keyword
try
{
..
}
catch (ExceptionType & ex)
{
...
throw;
}
- Imagine you're writing a low-level library class...
- Throwing a Different Exception
- It's usually desirable to shield the client programmer from low-level exceptions
- Too much low-level grunge detail!
- A better approach is as follows:
- Catch low-level exception(s)
- Throw higher-level exception(s) instead
try
{
...
}
catch (LowLevelExceptionType & ex)
{
...
throw HigherLevelExceptionType("Some high-level error message...");
}
- It's usually desirable to shield the client programmer from low-level exceptions
Well done. You have completed the tutorial in the C++ course. The next tutorial is
9. Dynamic Arrays and Vectors
Copyright © 2016 TalkIT®
If you would like to see more content like this in the future, please fill-in our quick survey.