Syllabus for Spring 2025 Computer Science II
CISC-2000-E01

This is all the guidance they gave me:

  1. Arrays/Vectors
  2. Pointers
  3. Dynamic Memory
  4. Classes
  5. Inheritance and Polymorphism
  6. Templates
  7. Operator Overloading

Commentary

Arays and pointers. The computer’s memory is a series of little containers called cells. Each cell has an identifying number, called its memory address. The address numbers start at 0, and go up to a big number that depends on how much money you paid for your memory.

An array of values is a series of values (e.g., ints, doubles, strings) located in the computer’s memory at evenly spaced addresses (e.g., 10, 20, 30, 40, etc). In the Fall semester (CISC-1600-E01), we accessed the values in an array by specifying their subscript numbers. In the Spring semester (CISC-2000-E01), we will access the values in an array by specifying their memory addresses. This will let our loops execute faster. A pointer is a variable that holds the memory address of another variable or of an element of an array. Instead of using an int variable to hold the subscript of an array element, we will use a pointer variable to hold the memory address of an array element.

Dynamic memory. When we wrote our programs in the Fall, we always knew how many elements our arrays would need to have:

	string a[] {       //an array of the names of the 50 states
		"Alabama",
		"Alaska",
		"Arkansas",
		//etc.
	};

	const int n {size(a)};   //the number of values in the array
But when we write programs in the Spring, we will not always know in advance how many elements our arrays would need. That means we will not always be able to create our arrays by writing a declaration for them. Instead, we will have to ask the operating system directly for a big chunk of memory that will hold the values of the array. If there is enough memory available, the operating system will give our program the memory address of a sufficiently large chunk. This address will be delivered to our program as a pointer variable. When we are done with the chunk, we will have to remember to give it back to the operating system.

Classes. In the Fall, we created a struct: a new type of variable that contained several (smaller) values inside of it. An object is like a struct, in that it can contain several values inside of it. Think of these values as the “internal organs” of the object. An object can also have functions (i.e., pieces of packaged code) attached to it, and these functions can automatically access the internal organs of the object. to which they are attached. We can set it up so that no other part of the C++ program can access the internal organs of the object.

So a complete description of a given type of object would list the variables inside the object (the internal organs), and the functions attached to the object that are the only way we can access these internal organs. A type of object is called a class of objects. The iternal organs of an object are called the data members of the object, and the functions attached to an object are called the member functions of the object. In other words, the study of objects is larely the study of packaging: identifying which functions can access which variables.

Inheritance [the hardest part of the course]. In C++, we can build up a complicated class of objects in stages or layers. We can start with a simple class that contains just a few data members and member functions. Think of the month structure that we made in the Fall. It had no member functions, but at least it had two data members:

	struct month {
		string name;
		int length;	//number of days
	};
Then we can build a bigger and better version of this class, with additional data members and member functions:
	struct betterMonth {
		//contains all the data memebers in a plain old month, plus ...
		double fahrenheit;  //average temperature
	};
An object of class betterMonth will have three data members (name, length, fahrenheit) because its class was built with a head start. The class automatically inherits all the data members that a plain old month had, and it also has one additional data member, the fahrenheit. This is a very simple example of building a bigger class out of a smaller one by means of inheritance.

A bigger and better class will often need bigger and better member functions. For example, suppose that there was a member function named print attached to our original class month. This print function prints the two data members inside of a month. But this function would not be adequate for printing all the data members inside of a betterMonth, because the betterMonth has an additional data member (fahrenheit) that a plain old month did not have. To print all the data in a betterMonth, we would need to have a bigger and better member function attached to it. This bigger and better member function would also be called print, so now we have two member functions with the same name.

We would like to write code that is flexible enough to handle a plain old month or an improved betterMonth. (Specifically, we would like to write functions that are flexible enough to receive arguments that might be plain old month objectss or improved betterMonth objectss.) We would like our code to automatically call the correct member function to print the plain old month or betterMonth that we receieve. A month should be printed by the original print member function attached to class month, and a bigger and better betterMonth should be printed by the bigger and better print member function attached to the bigger and better class betterMonth. Polymorphism is the art of making sure we select the correct print function in this situation.

Templates. Here are two functions whose logic is the same. The only difference between them is their data types.

int maximum(int a, int b)   //Return the bigger argument.
{
	if (a >= b) {
		return a;
	} else {
		return b;
	}
}

double maximum(double a, double b)   //Return the bigger argument.
{
	if (a >= b) {
		return a;
	} else {
		return b;
	}
}

A template will let us write this code once and for all, using the dummy name T for any data type we want to use:

//Now the function will accept a pair of arguments any type:
//int, double, float string, char, etc.

template <typenam T>
T maximum(T a, T b)   //Return the bigger argument.
{
	if (a >= b) {
		return a;
	} else {
		return b;
	}
}

Operator overloading. Deep inside of the computer, int addition and double addition are two very different operations. But we write both of them with the same symbol, +. This use of the same symbol to stand for two different operations is called operator overloading.

	int i {10};
	int j {20};

	double d {3.14158};
	double e {2.71828};

	cout << i + j << "\n";   //This + means integer addition.
	cout << d + e << "\n";   //This + means double  addition.

In the Spring we will create many new classes of objects. It would be convenient if we could use the same symbol, +, to add together objects of these new classes. For example, imagine

	investement i {1000000, 3};  //dollars, years
	investement j {2000000, 3};

	cout << i+j << "\n";
We will therefore overload the symbols + and << so that we can apply them to objects of the new classes that we create.

Possible textbooks

  1. Problem Solving with C++, 10th ed.
  2. Big C++: Late Objects, 3rd ed.