






Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Material Type: Notes; Class: Introduction to Object-Oriented Design; Subject: Computer Engineering; University: Syracuse University; Term: Unknown 1989;
Typology: Study notes
1 / 10
This page cannot be seen from the preview
Don't miss anything!







The midterm covers C/C++, object oriented design, and a bit on the Standard Template Library.
Questions you should be able to answer: What is a class? What is an object? What is encapsulation? What is inheritance? What is an operator? What is overloading? What is operator overloading? What is a data member? What is a member function? What is a public interface? What is information hiding? What is a constructor? Also, what is a default constructor? What does the copy constructor do? What is a destructor? What does the assignment operator do? When do you use “.” versus “->”? What’s the difference between the “public:” and “private:” tags? What does the “this” keyword refer to? What is a friend function? Where is friendship declared? Why would you use a templated function? What is the difference between a copy constructor and an assignment operator? What are access rights? What’s the difference between static and dynamic memory allocation? Why would you pick a linked list implementation over an array implementation? What’s the difference between call by reference and call by value?
Note: member function and method are synonymous.
In C, to display information to the screen and to read information from the keyboard, we use the printf and scanf functions.
C++ provides a cleaner solution by viewing the screen and keyboard as data streams (this abstraction extends to files as well). The cout and cin streams in C++ provide the same functionality as printf and scanf.
For example, the C code:
#include <stdio.h> /need when using printf and scanf/ int main() { int age; printf(“enter your age:”); scanf(“%d”, &age); return 0; }
Is equivalent to the C++ code:
#include
Dynamic memory allocation happens during runtime when the program asks the operating system to set aside a chunk of memory for its use. When the program is done with a chunk of memory, it tells the operating system that it is finished with the memory. In C, these two tasks are accomplished with malloc and free. The malloc function requests the memory from the operating system and returns a pointer to that memory to the program. When freeing the memory, you pass the pointer to the allocated memory to the free function.
C++ provides a cleaner implementation for requesting and relinquishing dynamic memory. The new and delete functions provide the same functionality as malloc and free.
For example, the C code:
#include <stdio.h> #include <stdlib.h> int main() { int ages; /pointer/ ages = (int)malloc(sizeof(int) * 3); /allocates an array of 3 integers/ ages[0] = 17; ages[1] = 18; ages[2] = 21; printf(“ages = %d %d %d\n”, ages[0], ages[1], ages[2]); free(ages); /returns memory to operating system/ return 0; }
Is equivalent to the C++ code:
#include
Scope is a term that indicates where a variable exists in a program. There are four different scope areas:
As an example consider the following code:
#include
int myGlobalScope = 42; //myGlobalScope has global scope
void Func1() { int myFuncScope; //myFuncScope has function scope
cout << “myGlobalScope=” << myGlobalScope << endl; //we can use myGlobalScope within a function because it has global //scope and is therefore available anywhere
myFuncScope = 84 / myGlobalScope; cout << “myFuncScope=” << myFuncScope << endl; //we should get “myFuncScope=2” for output
int Student::count = 0; //one time initializer
int main() { cout << Student::count << endl; //output: 0 Student s1(“bill”, 1111); Student s2(“kim”, 2222); cout << Student::count << endl; //output: 2 cout << s1.count << endl; //output: 2 cout << s2.count << endl; //output: 2 return 0; }
Since the static variable exists even when no objects of the class exist, we can get at it by calling “Student::count”, that is, proceed the static variable with the name of the class it belongs to. Once we have objects of the Student class, we can access count just like any other public component of the class, for example, “s1.count”.
Everyone’s favorite subject.
First, pointer variables contain memory addresses as their values. We typically draw pointer as a box with an arrow coming out of it which ends at the block of memory the pointer points at.
Pointers should be initialized either when they are declared or in an assignment statement. A pointer may be initialized to 0, NULL, or any address. A pointer with the value 0 or NULL points to nothing.
The &, or address operator, us an operator that returns the address of its operand. For example,
int y = 5; int *yPtr = &y;
The second line assigns the address of the variable y to the pointer variable yPtr. Variable yPtr is then said to point to y.
The * operator, commonly referred to as the dereferencing operator, returns the value at the memory location pointed to by a pointer. For example,
cout << y << “\t” << (*yPtr) << endl;
The above line produces “5 5” as output. The & and * operators are inverses of one another.
Pointers are used then calling by reference in functions. Pointers and arrays may be used almost interchangeably. An array name can be thought of as a constant pointer.
A reference is an alias for its corresponding variable. References are often used in call-by-reference function arguments in C++. To indicate that a function parameter is passed by reference, simply follow the parameter’s type in the function prototype by &. For example,
#include
void Func(int &aRef) { aRef += 10; }
int main() { int a = 17; cout << “a=” << a << endl; Func(a); cout << “a=” << a << endl; return 0; }
The program output is “a=17” on the first line, and “a=27” on the second line. Therefore, “a” must have been passed by reference.
In C, you define an abstract data type by using the “struct” keyword. For example,
struct Course { char name[7]; int section; int creditHours; };
This defines a record that contains the name of a course as a string (a null terminated array of characters), the course’s section number as an integer, and the number of credit hours also as an integer. The structure only defines the fields and their corresponding data types; it does not define any operations that may be performed on those fields.
The above struct can be rewritten as a class as follows:
class Course { public: char name[7]; int section; int creditHours; };
This is the minimum you would have to do to convert to a class. However, the power of classes is pretty much untapped here.
To begin to harness the power of classes, you will want to employ encapsulation (information hiding). Modifying the above class definition to hide its data members is achieved as follows:
class Course { private: char name[7]; int section; int creditHours; };
While this effectively hides name, section, and credit hours, it does so too well – we have no access to these data members at all. Access is achieved by adding member functions (methods) as part of the class’s public interface. For instance,
class Course { private: char name[7]; int section; int creditHours; *public: void SetName(char n) { strcpy(name, n); } void SetSection(int s) { section = s; } void SetCreditHours(int ch) { creditHours = ch; } };
These publicly defined methods make up the classes current public interface. They allow us to set the name, section, and credit hours. Unfortunately, we don’t have a way to get the values back. We must, therefore, extend the public interface. For instance,
class Course { private: char name[7]; int section; int creditHours; public: void SetName(char *n) { strcpy(name, n); } void SetSection(int s) { section = s; }
Remember, the copy constructor is a true constructor, it will only be called when an object of type Course is being created (and only when another object of type Course is passed as a parameter). We would therefore also like a way to copy the contents of an existing Course object into the contents of another existing Course object. This is accomplished by overloading the assignment operator. For instance,
class Course { private: char name[7]; int section; int creditHours; public: void SetName(char *n) { strcpy(name, n); } void SetSection(int s) { section = s; } void SetCreditHours(int ch) { creditHours = ch; } char *GetName() const { return name; } int GetSection() const { return section; } int GetCreditHours() const { return creditHours; } Course(char *n = “”, int s = 0, int ch = 0) { strcpy(name, n); section = s; creditHours = ch; } Course(const Course &c) { strcpy(name, c.name); section = c.section; creditHours = c.creditHours; } *const Course &operator=(const Course &c) { strcpy(name, c.name); section = c.section; creditHours = c.creditHours; return this; } };
Notice that the assignment operator returns a reference to the course being modified – that is why we return “*this”. The “this” pointer refers to the object being modified. By having a return type, we can string together assignments (such as “a=b=c;”).
Constructors are called when an object is created. To satisfy our need for symmetry, destructors are called when an object is destroyed. For our Course class we don’t really need to implement a destructor, but for the sake of the example, here goes:
class Course { private: char name[7]; int section; int creditHours; public: void SetName(char *n) { strcpy(name, n); } void SetSection(int s) { section = s; } void SetCreditHours(int ch) { creditHours = ch; } char *GetName() const { return name; } int GetSection() const { return section; } int GetCreditHours() const { return creditHours; } Course(char *n = “”, int s = 0, int ch = 0) { strcpy(name, n); section = s; creditHours = ch; } Course(const Course &c) { strcpy(name, c.name); section = c.section; creditHours = c.creditHours; } const Course &operator=(const Course &c) { strcpy(name, c.name); section = c.section; creditHours = c.creditHours;
return *this; } ~Course() { cout << “do nothing destructor\n”; } };
Remember, the destructor takes on the name of the class prefixed with a “~” character. The destructor has no return type. You would typically free up system resources associated with the object being destroyed.
The only reason we talked about template functions was to lead in to the Standard Template Library. You need to have at least a rudimentary understanding of what templates are. Here’s a brief example to get you used to the notion.
Let’s say that we want to develop a swap function that is independent of the data type. Instead of writing overloaded functions for each data type your program might want to swap, we can use a template function. For instance,
template
All function templates begin with the keyword template followed by a list of formal parameters to the function template enclosed in angle brackets (< and >); each formal parameter that represents a type must be preceded by the keyword class (whether the type is actually a class or not). So, in our main we might have something that looks like:
int main() { int a = 3, b = 5; double c = 7.7, d = 9.9; Swap(a, b); Swap(c, d); }
When the compiler encounter the line “Swap(a, b);” it knows that a function template has been provided for Swap. As such, it determines that a’s data type matches b’s (which it does), then it generates an integer version of the Swap function (at compile time). As such, the following function now exists:
//this function is compiler generated: void Swap(int thing1, int thing2) { int temp; temp = thing1; thing1 = thing2; thing2 = temp; }
When the compiler then encounter the line “Swap(c, d);” it still knows that a function template has been provided for Swap. Again, it determines that c’s data type matches d’s, then it generates a double version of the Swap function (at compile time). As such, the following function now exits:
//this function is also compiler generated: void Swap(double thing1, double thing2) { double temp; temp = thing1; thing1 = thing2; thing2 = temp; }
Since C++ allows for overloading of operators and functions, there is no problem having two functions named Swap – they have different data types in their parameter lists, so they can be distinguished. The astute observer will recognize that the compiler is merely substituting the templates formal parameter (T) with the data type of the calling arguments (int in the first case, double in the second).
You should be familiar with the steps of the object oriented design method (see lecture 5):
Class/Object Model:
Dynamic Model:
Functional Model: