Setting Up the Development Environment

For this course, I am going to be using Visual Studio Community Edition which can be downloaded for free. The important point to remember when installing it is that support for C++ may not be included automatically so you need yo make sure that under the Workloads tab, Desktop development with C++ is selected. If you install Visual Studio without selecting this, you can add it later by selecting the Tools menu and then Get Tools and Features and this opens up the same screen you see when installing VS. You can also make some other changes here such as installing additional language packs or making changes to the installed components.

Elements of Object-Oriented Programming

Some basic concepts of object oriented programming

Modelling

		- a representation of reality
		- we can model anything
		- programming with objects largely involves deciding what to include in (or exclude from) our models

Example - a car

Purpose of app Examples of properties we might include
A sales app Price, make, model, seats, mileage
A rideshare app No of passengers, trunk size
A parking app Size

These are all abstractions of a car where we describe it in terms of its essential features. In a sales app, for example, a car is quite a complex object and we could use hundreds of properties to describe it. At the other end of the scale is a parking app, and this might only be concerned with how much space the car will occupy.

Encapsulation

		- keep data and operations within the same (appropriate) model
		- models must be concise
		- models must only contain information about themselves (for example, a car model shouldn't include data about the cost of petrol).

Classes

		- how models are represented in C++
		- contain two types of members
			- data members (eg Car.make)
			- functions (eg Car.paint())
			- An object is an instance of a class

Access Specifiers

Members can be public, private or protected.

		- public members can be accessed from outside the class
		- private members can only be accessed from inside the class
		- protected members are like private members but can be access from a subclass (that is, a class that inherits from the class with the protected members)

Inheritance

		- a class can have subclasses which inherit members from the parent class
		- the subclass can expand on the parent class by adding or modifying members

An example of this might be a class called Animal with a property called legs that records the number of legs an animal has. A subclass called Dog would inherit that property. Another subclass called Bird might also have that property but might have an additional property called wings.

Polymorphism

Let's imagine we want to add a function called speak() which when called, outputs some string representing the sound made by an animal. For example, if we call this function on a Dog object, the output might be 'Woof', for a Cat object, this might be 'Meow' and so on. The first question we need to consider is where will we define this function. There are several options

 - the simplest solution would be to define it as a function of the Animal class - it would then be accessible to any subclass of Animal. The downside is that if the method is called on an object from a subclass (a Dog or Bird object) the same method is called every time so the function is generic meaning that the behaviour is the same regardless of what type of Animal it is called on. We might customise it by passing some value from the object calling the function to the function that identifies the animal type and acts accordingly. Unfortunately, customising the function like that really means that this is no longer the simplest solution!

 - another solution would be to implement the function in any subclass that needs it. This makes it much simpler to customise the function because we know in advance what type of Animal object can call it. Assuming we implement the function in every subclass, in this example this means implementing it in both the Dog and Bird class, if we then call the function on a Dog object, the function implemented in the Dog class will be executed. Similarly, if it is called on an object of the Bird class, the function implemented in the Bird class will be executed. The calls will look the same

  • aBird.speak()

  • aDog.speak()

but we are calling a different function amd this is polymorphism. Since the Bird and Dog classes have the same parent, they are referred to as sibling classes so if we are implementing the same function (or functions) in each, we can also consider them to be poylmorphic classes.

 - we can combine these approaches if the function has a significant amount of code that is going to be the same in the subclasses. We can put this code in a function implemented in the Animal class and then define the same function in, let's say, the Dog class with the behaviour specific to Dog objects. When we call the function on a Dog object, we can either call the function from the parent class or we can call the function implemented in the Dog class, depending on whether we want the general or the specific code to be executed.

 - there is another option which is probably too advanced for this course which is to implement Animal as an abstract class with a speak() function. This means that we specify the function and possibly a list of arguments in the parent class (Animal) but we don't implement it. If we then create a subclass, like Dog or Bird, the subclass must implement the speak() function. Using this method, we can guarantee that the Dog or Bird class will implement the speak() function.

Creating a Simple Program in C++

You may know that it is traditional to write a 'Hello World' program as your first in any programming language and this is important for a couple of reasons. Firstly, it acts as a very brief introduction to the syntax of the language but more importantly, it's a very simple program so you can use it to check whether your IDE is correctly installed. In other words, it helps to make sure that you are able to write and run (in this case) C++ programs on your PC.

Since I originally learned C from a book byh Dan Gookin, I will follow his practice of writing a program that outputs 'Goodbye, cruel world!' instead. It really doesn't matter what text you choose to output. Our first program is

	// goodbye.cpp : This file contains the 'main' function. Program execution begins and ends there.
	//

	#include <iostream>

	int main() {
		std::cout << "Goodbye, cruel world!"  << std::endl;
	}

Let's look at this line by line.

	#include <iostream>

This is a preprocessor directive. In other words, it is something that the compiler will look at before compiling the code and it is really just telling it where to find the methods it needs for outputting text to the screen, accepting input from a keyboard and so on.

The next line

	int main() {

is the name of the functions. In C++, the main function must return an integer value which indicates suceess or failure (traditionally, a 0 return value indicates success). We will cover functions in more depth later so for now, it's only necessary to know that you have to have a main function because this is where execution of the code starts.

In this example, the parameter list is empty so main will not accept any arguments but we could also set it up to receive an array of arguments like this.

	int main(*argv[]) {

Finally we have the line of code that is actually doing something in this program.

		std::cout << "Goodbye, cruel world!"  << std::endl;

The cout is an object for cgaracter output and it represents the output window. We use << to send out text output to cout. Another useful object is endl which represents an end of line character so we get any other output on a new line.

Both cout and endl are part of the std namespace so we can add the line

	using namespace std;

between the first and second lines. Our code is specifying the namespace by adding std:: in front of an object (which is how we tell the compiler that they are part of the std namespace but if we add this extra line, std effectively becomes the default namespace and we don't need to specify it so we can change the output line to

		cout << "Goodbye, cruel world!"  << endl;

The full version of the code then becomes

	#include <iostream>

	using namespace std;

	int main() {
		cout << "Goodbye, cruel world!"  << endl;
	}

and this will work in exactly the same way as the original version. Bear in mind that this is a practice which makes the coding a little bit easier but it is generally considered a trick to help new coders and it can cause some problems so it is not considered to be a good practice. However, it is probably okay to use this trick in the sort of simple examples of code covered in this course. Personally, I think that you should try to adopt best practices right from the start and adding the namespace in front of each object helps with learning (at least in learning which namespaces objects belong in) so it is unlikely that we will see using namespace again in these notes.

Challenge: Console Interaction

For this challenge, we just want to have the user input a string representing their name. We then want to output some string with a message that inclused the user's name. This will probably require two or three lines of code (excluding any preprocessor directives).

	1 - a line of code prompting for the users name
	2 - a line of code allowing the user to input their name
	3 - a line of code printing out the required message

Both the first and third lines are output statements, the second line is an input statement.

	#include <iostream>
	#include <string>

	using namespace std;

	int main() {

	}

This is mostly the same as we saw in our first program and we are including the line, using namespace std; but there is one additional line. We want to be able to use strings in the program so we need to include the string header file.

	#include <string>

We will need a string variable to hold the name so we will call it name.

	str name;

In a very simple example like this, in some ways, it doesn't matter where we put this line of code. If we put it before the main function, it will have global scope and be accessible anywhere within the program. If we put it inside the main function, its scope will be local to the main function and it will not be accessible outside that function. Unless, that is, we declare it as public. We omitted that so in this case, it actually is public since public is the default scope.

The point in mentioning this is that although it doesn't matter here - its a small sample program and it is very easy to see and understand every line of code but that will not usually be the case in a real-world example. Best practice is to declare the variable in the correct place - that is, inside the function where it will be used and declare it as private or protected but not public. In this case, that means inside the main function.

The main function is the same as before and that's where we will put our three lines of code alongside our string variable declaration. Our first line is

	cout <<"Please enter your name: ";

Notice that we didn't add an endline object because we want the user to type their name on the same line.

The second line, the input line, will is

	cin >> name;

Finally, we will output the name with some appropriate message.

	cout << "Hello, " << name << ".  Are you enjoying Learning C++?" <<endl;

When we run this, we get the output

	Please enter your name: Philip
	Hello, Philip.  Are you enjoying Learning C++?

Solution: Console Interaction

My completed solution for the challenge is:

	#include <iostream>
	#include <string>

	using namespace std;

	int main() {
		string name;
		cout << "Please enter your name: ";
		cin >> name;
		cout << "Hello, " << name << ".  Are you enjoying Learning C++?" << endl;
	}

The course solution is identical except for the variable names and the messages displayed. It also included a line returning 0 like this.

	return (0);

This is not strictly required. The following image shows the result of running my version of the solution.

Output from my solution to the Console Interaction challenge

As you can see, when the program terminated, it terminated successfully and returned a zero value. I'm not sure what the point of explicitly returning this is. The program is simple enough so that we can immediately see if it completes successfully, we see the appropriate message being output in the console. Explicitly returning a zero like this guarantees that a zero will be returned. In this case, if the program doesn't complete successfully, it would most likely crash anyway.